并发多任务编程 - 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

GCD串行并发队列扫盲

文章链接:http://www.henishuo.com/gcd-serial-concurrency-queue/
  • woaifen3344
  • woaifen3344
  • 2016年04月06日 16:40
  • 669

iOS之利用GCD信号量控制并发网络请求

利用信号量来解决网络请求耗时所导致的多线程处理时的一些问题
  • Cloudox_
  • Cloudox_
  • 2017年05月03日 09:56
  • 3276

关于GCD中串行队列、并发队列和同步执行、异步执行的探讨

Dispatch Queues Dispatch queue是一个对象,它可以接收任务,并将任务以先到先执行的顺序来执行。Dispatch queue可以使并发的或串行的。并发任务会基于系统负载来合...
  • qq_30515765
  • qq_30515765
  • 2016年06月30日 15:07
  • 1785

GCD之主队列、全局并发队列、以及同步任务的执行

主队列:专门负责在主线程上调度任务,不会在子线程上调度任务,在主队列不允许开新线程。 主队列的特点:只在主线程运行,不开新线程。 异步执行:会开新线程,在新线程执行。 异步执行特点:不需要马上执行。 ...
  • u013087513
  • u013087513
  • 2015年10月21日 19:29
  • 1746

ios多线程操作(五)—— GCD串行队列与并发队列

GCD的队列可以分为2大类型,分别为串行队列和并发队列      串行队列(Serial Dispatch Queue):      一次只调度一个任务,队列中的任务一个接着一个地执行(一个任务执...
  • u011058732
  • u011058732
  • 2015年03月19日 21:53
  • 7453

iOS GCD之dispatch_group的使用(多个文件并发上传)

NSMutableArray *imageURLs= [NSMutableArray array]; dispatch_group_t group = dispatch_group_create();...
  • Xoxo_x
  • Xoxo_x
  • 2017年07月27日 09:55
  • 602

GCD 同步 异步 串行 并发的使用方法.例子 和特点

// dispatch_sync : 同步,不具备开启线程的能力 // dispatch_async : 异步,具备开启线程的能力 // 并发队列 :多个任务可以同时执行 // 串行队列 :...
  • qq_27074387
  • qq_27074387
  • 2016年05月13日 12:48
  • 778

GCD优先级子队列扫盲

概述 本篇来研究一下GCD中的子队列如何设置优先级。我们知道全局队列可以有四种优先级可以设置,而我们自己创建的队列并没有参数可以指定优先级,那么我们有办法做到按优先级来执行任务吗? 答案是肯定的。...
  • liangliang2727
  • liangliang2727
  • 2016年05月11日 01:52
  • 1074

GCD:创建并发队列

网上各种关于GCD队列的文章中都说队列分为串行和并行队列,串行队列有主队列和通过dispatch_queue_create(const char *label, NULL)创建的队列,并行队列有dis...
  • sunhao92
  • sunhao92
  • 2015年06月26日 17:11
  • 499

GCD中的dispatch_barrier_async函数的使用(栅栏函数)

void dispatch_barrier_async ( dispatch_queue_t queue, dispatch_block_t block ); 参数 queue: 将barri...
  • MouXiaoxiong
  • MouXiaoxiong
  • 2016年11月28日 16:44
  • 909
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:并发多任务编程 - GCD 初学者扫盲
举报原因:
原因补充:

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