并发多任务编程 - GCD 初学者扫盲

转载 2013年12月05日 14:32:06
现代计算设备都具备多核心处理器的能力,而并发的多任务可以同时运行在多个不同的处理核心上,有利于提高系统性能和用户的响应。对于开发人员来说,一般通过操作系统提供的多任务编程接口来实现,其中涉及多线程、多进程、以及相应的同步互斥操作,在代码实现上较复杂,要考虑的方面也很多。
所以,Apple提供了一种更加有效更加弹性的操作多任务的方式GCD(Grand Central Dispatch),它封装了操作线程的具体细节,无须顾及线程创建、同步等代码,你只要关注具体的任务代码就可以了。GCD负责将任务分发到相应的线程上去执行。

 
GCD包含以下元素:

1. Operation Queues

操作队列,即包含所要操作的任务的队列。在iOS中,NSOperation类定义了要操作的任务。它本身是个抽象基类。NSOperation可以设定不同任务之间的依赖关系、定义任务完成后所要执行的代码块、支持KVO通知机制、支持任务的优先级、支持运行中中断任务操作。

Foundation框架也提供了两个NSOperation的子类来方便操作。

NSInvocationOperation:用在任务代码以函数的方式进行封装的情形,通过@selector的方式调用。

NSBlockOperation:用在任务代码以代码块对象的方式进行封装的情形。

使用代码块时的注意事项: 

  • 代码块中引用指针对象和大的数据结构时,应注意在代码块被分配到线程执行时,指针指向的数据仍然是有效的。


2. Dispatch Queues

分发队列。顾名思义就是将所要操作任务分发到具体线程的队列。分发队列是FIFO队列,它本身是线程安全的,即使用它之前不需要事先上锁和同步。

GCD提供了以下类型的队列:

Serial:(又称为private dispatch queues

同一个分发队列中的任务是串行执行的,该队列确保其中的任务是按顺序一个一个执行的。这个队列对象是基于引用计数的,操作它时需注意分配和释放引用记数。

创建该队列代码:

dispatch_queue_t queue;

 

queue = dispatch_queue_create("com.example.MyQueue", NULL);

Concurrent:(又称为global dispatch queue

分发队列中的任务是并行执行的。

获取该队列代码:

dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

Main dispatch queue:

应用程序的主线程,实际上它也是Serail线程,但是它是全局的。


3. Execute Queues

队列加载任务:

有两种方式,同步加入、异步加入。同步的方式将阻塞当前线程,直到任务线程执行完毕才继续执行。

同步方式:dispatch_sync  dispatch_sync_f .

异步方式:dispatch_async  dispatch_async_f .

注意:不能在同一个队列中使用同步方式加载任务。

主线程中加载任务:

挂起、继续执行:


4. Dispatch Semaphore
资源同步。
这种GCD信号量效果和传统信号量一样,但是性能更高。因为它大部分情况下不需要进入系统内核空间,只有在资源未准备好时才进入系统内核将该线程挂起等待。
示例代码:

// Create the semaphore, specifying the initial pool size

dispatch_semaphore_t fd_sema = dispatch_semaphore_create(getdtablesize() / 2);

 


// Wait for a free file descriptor

dispatch_semaphore_wait(fd_sema, DISPATCH_TIME_FOREVER);

fd = open("/etc/services", O_RDONLY);


// Release the file descriptor when done

close(fd);


dispatch_semaphore_signal(fd_sema);


5. Dispatch Group
如果要对超过一个以上任务进行同步,可以使用这种方式。

示例代码:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_group_t group = dispatch_group_create();

 


// Add a task to the group

dispatch_group_async(group, queue, ^{

// Some asynchronous work

});

 


// Do some other work while the tasks execute.

 

// When you cannot make any more forward progress,

// wait on the group to block the current thread.


dispatch_group_wait(group, DISPATCH_TIME_FOREVER);


// Release the group when it is no longer needed.

dispatch_release(group);




6. Dispatch Sources
对于系统更底层更广泛的通知,可以使用这种机制。
  • Timer dispatch sources 产生周期性的时间通知.
  • Signal dispatch sources 传统的linux/unix系统信号通知.
  • Descriptor sources 基于文件、socket套接字的描述符通知:
    • 当有数据可以读时
    • 当数据可以写时
    • 当文件系统中的文件被删除、移动、重命名时
    • 当文件元信息被修改时
  • Process dispatch sources 当进程发生变化时通知:
    • 进程退出
    • 当进程执行类fork/exec系统调用
    • 当一个信号被发送到进程时
  • Mach port dispatch sources Mach-related相关事件通知.
  • Custom dispatch sources 用户自定义事件.
更详情资料请参考官方文档:http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/GCDWorkQueues/GCDWorkQueues.html

相关文章推荐

多线程编程(3、多任务并发处理)

例:假设我们有个方法要执行100次,得到100次返回的结果总和。串行执行 static void Main(string[] args) { Se...

GCD编程dispatch_sync(同步)和dispatch_async(异步)方式执行并发队列任务区别

GCD编程dispatch_sync(同步)和dispatch_async(异步)方式向并发队列添加任务区别

Linux多任务编程(二)---fork()函数及其基础实验

fork()函数      在 Linux 中创建一个新进程的唯一方法是使用fork()函数。fork()函数是 Linux 系统中一个非常重要的函数,和咱们以前遇到过的函数由一些区别,因为它看起来...

Linux多任务编程(四)---exit()函数及其基础实验

exit()和_exit()函数 函数说明    创建进程使用fork()函数,执行进程使用exec函数族,终止进程则使用exit()和_exit()函数。当进程执行到exit()或_exit()...

Linux多任务编程学习笔记

Linux多任务编程一、进程机制 多任务处理:指用户可以在同一时间内运行多个应用程序,是使用某种调度策略支持多个任务并发执行。 注: 某种调度策略指的是某种调度算法,按次序,优先级,依次循环。 ...

uCOS-II多任务编程

  • 2013-04-26 09:27
  • 368KB
  • 下载

uCOS-II多任务编程设计

  • 2013-06-05 10:49
  • 368KB
  • 下载

Linux系统编程——多任务的同步与互斥

现代操作系统基本都是多任务操作系统,即同时有大量可调度实体在运行。在多任务操作系统中,同时运行的多个任务可能: 都需要访问/使用同一种资源 多个任务之间有依赖关系,某个任务的运行依...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)