关闭

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

标签: GCD
471人阅读 评论(0) 收藏 举报
分类:
现代计算设备都具备多核心处理器的能力,而并发的多任务可以同时运行在多个不同的处理核心上,有利于提高系统性能和用户的响应。对于开发人员来说,一般通过操作系统提供的多任务编程接口来实现,其中涉及多线程、多进程、以及相应的同步互斥操作,在代码实现上较复杂,要考虑的方面也很多。
所以,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

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3965次
    • 积分:56
    • 等级:
    • 排名:千里之外
    • 原创:0篇
    • 转载:10篇
    • 译文:0篇
    • 评论:0条
    文章存档