GCD(Grand Central Dispatch),主要用于多线程编程。它屏蔽了繁琐的线程实现及管理细节,将其交由系统处理。开发者只需要定义任务block(在底层被封装成dispatch_continuation_t结构体),并提交到正确的dispatch queue中。GCD包含dispatch queue和dispatch source。

一、dispatch queue是FIFO队列,分为两种:

1、serial(串行),队列中的block同一个时刻只会派发给一个线程,所以要等当前block执行完,才会开始执行下一个block。

2、concurrent(并行),队列中的block同一个时刻可能会派发给多个线程,所以多个block可以同时执行。

3、苹果官方说明:

Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue.The currently executing task runs on a distinct thread (which can vary from task to task) that is managed by the dispatch queue.

注意:串行队列中不同block可能在不同线程执行!

二、使用dispatch queue的方法,也分为两种:

1、dispatch_sync(同步),调用dispatch_sync方法的线程会被阻塞,直到block执行结束。在当前线程调用dispatch_sync方法可能会导致死锁!!!

2、dispatch_async(异步),调用dispatch_async方法的线程不会被阻塞。

NSLog(@"1"); // 死锁,只会输出1
dispatch_sync(currentQueue, ^{NSlog(@"2"); // block也提交到当前线程对应的队列
});
NSlog(@"3");

死锁的理解:

1、dispatch_sync方法调用和block调用,是当前线程需要处理的两个任务。

2、dispatch_sync方法调用首先提交到队列中。

3、然后block调用提交到队尾,需要等待dispatch_sync方法调用完成。

4、而dispatch_sync方法调用,又需要等到block执行结束才能返回。这就形成了等待环,即死锁。

解决死锁:把block交由另一个线程执行

// 依次输出1、2、3
NSLog(@"1");
dispatch_sync(notCurrentQueue, ^{NSlog(@"2"); // block提交到另外一个线程对应的队列
});
NSlog(@"3");   

三、创建队列:

dispatch_queue_t dispatch_queue_create(const char *_Nullable label, dispatch_queue_attr_t _Nullable attr);
// label:队列的唯一标识,方便调试
// attr:队列类型,NULL或者DISPATCH_QUEUE_SERIAL表示串行,DISPATCH_QUEUE_CONCURRENT表示并行
dispatch_queue_t serialQueue = dispatch_queue_create("com.tencent.wechat.file", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.tencent.wechat.network",DISPATCH_QUEUE_CONCURRENT);  

在MRC下,dispatch_queue_create创建的队列,需要用dispatch_release释放掉。

四、有时候,并不需要开发者创建队列,系统已经提供了两种很好用的队列。

主队列,对应主线程,是个串行队列:

dispatch_queue_t serialMainQueue = dispatch_get_main_queue();

全局队列,是并行队列:

dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);
// identifier:队列优先级
// flags:通常填0
dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  

五、dispatch_after用于延迟执行任务:

void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);
// 3秒后提交block到主队列,这个时间并不精确,得看当时线程的繁忙程度
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{});

六、dispatch_suspend和dispatch_resume:

1、dispatch_suspend,挂起队列,只会暂停还没执行的任务,已经在执行的任务不会被影响。

2、dispatch_resume,恢复队列,继续调度还没执行的任务。

3、注意,resume一个没有被suspend的队列会导致crash!

七、dispatch_once

详见:https://www.cnblogs.com/yangwenhuan/p/9603472.html

八、dispatch group

在多个并行block都执行完,这就可以用到dispatch group

九、dispatch_set_target_queue

修改优先级

十、dispatch_barrier_async

barrier,顾名思义,添加一个障碍,就是就是个同步点。

dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// blk1, blk2, blk3并行执行
dispatch_async(globalConcurrentQueue, blk1);
dispatch_async(globalConcurrentQueue, blk2);
dispatch_async(globalConcurrentQueue, blk3);
// blk1, blk2, blk3全部执行完,才开始执行blk4
dispatch_barrier_async(globalConcurrentQueue, blk4);
// blk4执行完,才开始并行执行blk5, blk6
dispatch_async(globalConcurrentQueue, blk5);
dispatch_async(globalConcurrentQueue, blk6);

十一、dispatch_apply

提交特定数量的block到队列中,并等待全部执行结束。dispatch_apply存在与dispatch_sync一样的死锁问题,因此推荐把dispatch_apply放到dispatch_async中执行。

dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, q, ^(size_t iter) {NSLog(@"iteration[%zu]", iter);
});
NSLog(@"done");输出:
iteration[3]
iteration[2]
iteration[0]
iteration[4]
iteration[1]
iteration[5]
iteration[9]
iteration[8]
iteration[7]
iteration[6]
done // 最后输出一定是这个 

十二、dispatch semaphore

dispatch semaphore是信号量的封装,可用于实现线程安全,相比串行队列,粒度更小

// 创建信号量,初始值可以不为1
dispatch_semaphore_t s = dispatch_semaphore_create(1);
// 阻塞等待信号量大于等于1
dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER);
// 信号量减1,开始执行临界区代码/* 临界区代码 */// 临界区代码执行结束,信号量+1,最先等待信号量的线程得到执行
dispatch_semaphore_signal(s);

十三、dispatch io

// 获取文件描述符
dispatch_fd_t fd = open(file_path, O_RDWR);
// 创建用于处理dispatch io block的队列
dispatch_queue_t queue = dispatch_queue_create(queue_name, NULL);
// 创建dispatch io,绑定文件描述符
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_STREAM, fd, queue, ^(int error) {// 异常close(fd);
});
// 设置一次最多读取的字节数
dispatch_io_set_high_water(io, size);
// 这里书上说会使用global queue来并发读,但是实践没看出来,懂的同学请多多指教
dispatch_io_read(io, 0, max_size, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {// dispatch_data_t转NSStringdispatch_data_apply(data, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {NSString *sData = [[NSString alloc] initWithBytes:buffer length:size encoding: NSUTF8StringEncoding];return true;});
});

十四、dispatch queue VS NSThread, pthread

利用NSThread和pthread也是可以进行多线程编程的,但是

1)需要自己实现线程管理,如分配多少线程、什么时候分配、什么时候销毁等等

2)性能很难比dispatch queue好,因为dispatch queue是基于XNU内核的workqueue实现的(中间还有一层封装是Libc中的pthread_workqueue)

十五、dispatch source

dispatch source是内核kqueue的封装。kqueue是一种多路复用技术,用于监听内核的各种事件通知,并做出相应处理。因为利用回调代替轮询,所以kqueue的CPU占用率很小。

// 创建source
dispatch_source_t dispatch_source_create(dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t queue);
// 取消source,已经在执行的handler会继续执行完,还没执行的不再执行
void dispatch_source_cancel(dispatch_source_t source);
// 事件source发生时,执行handler
void dispatch_source_set_event_handler(dispatch_source_t source, dispatch_block_t handler);
// 取消source时,执行handler
void dispatch_source_set_cancel_handler(dispatch_source_t source, dispatch_block_t handler);
// 启动source
void dispatch_resume(dispatch_object_t object);

十六、dispatch queue和block的持有关系

block持有dispatch queue

参考链接:

https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

转载于:https://www.cnblogs.com/yangwenhuan/p/9439720.html

Objective-C GCD深入理解相关推荐

  1. GCD API 理解 (一)

    资料先行 GCD 深入理解:第一部分 GCD 深入理解:第二部分 以上两篇文章是关于GCD讲的比较好的文章,翻译自raywenderlich,该网站有很多关于iOS 开发的优秀文章. 引子 iOS 开 ...

  2. GCD 深入理解:第一部分

    本文翻译自 http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1 原作者:Derek Selander 译 ...

  3. GCD深入理解(一)

    虽然 GCD 已经出现过一段时间了,但不是每个人都明了其主要内容.这是可以理解的:并发一直很棘手,而 GCD 是基于 C 的 API ,它们就像一组尖锐的棱角戳进 Objective-C 的平滑世界. ...

  4. GCD 深入理解(一)

    本文由@nixzhu翻译至raywenderlich的<grand-central-dispatch-in-depth-part-1> 虽然 GCD 已经出现过一段时间了,但不是每个人都明 ...

  5. 关于GCD执行任务的理解

    2019独角兽企业重金招聘Python工程师标准>>> #pragma markf - 用异步函数往并发队列中添加任务// 创建并行队列dispatch_queue_t queue ...

  6. 【精】iOS知识树,知识点(包括对象、Block、消息转发、GCD、运行时、runloop、动画、Push、KVO、tableview,UIViewController、提交AppStore)

    本文旨在总结iOS知识网络,知识点,该知识网络罗列出常见UIKit.Foundation的对象特点和一些使用经验,可以看成是一本书:文本编辑采用树的形式,对知识点进行罗列,并标注一些使用经验(★)希望 ...

  7. iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用(上)

    2017-07-08 remember17 Cocoa开发者社区 目的 本文主要是分享iOS多线程的相关内容,为了更系统的讲解,将分为以下7个方面来展开描述. 多线程的基本概念 线程的状态与生命周期 ...

  8. 【转】iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD

    转自容芳志的博客 简介 iOS有三种多线程编程的技术,分别是: (一)NSThread  (二)Cocoa NSOperation (三)GCD(全称:Grand Central Dispatch) ...

  9. 使用GCD(转自唐巧的技术博客)

    原文链接:http://blog.devtang.com/2012/02/22/use-gcd/ 什么是 GCD Grand Central Dispatch (GCD) 是 Apple 开发的一个多 ...

  10. Swift 3.0中GCD的常用方法

    随着苹果推出swift3.0,很多API都发生了变化,下面我就来总结下GCD的一些常用API用法. 首先为了方便先定义几个属性: class ViewController:UIViewControll ...

最新文章

  1. 深度学习-语义分割总结
  2. 【深度学习】深度学习手写代码汇总(建议收藏,面试用)
  3. 岗位推荐 | 微软AI Research Group招募自然语言处理AI算法研究实习生
  4. VTK:Rendering之StripFran
  5. asp.net 调用本地php,.NET_Asp.net获取服务器指定文件夹目录文件并提供下载的方法,本文实例讲述了Asp.net获取服务 - phpStudy...
  6. [C++STL]常用算术生成算法
  7. Java CAS 和ABA问题
  8. CentOS系统Tomcat 8.5/9部署SSL证书
  9. kafka自定义分区实战
  10. 稳扎稳打Silverlight(30) - 2.0Tip/Trick之Silverlight.js, Silverlight.supportedUserAgent.js
  11. 页式管理--物理地址计算问题小结
  12. 华为HCIE认证考试简介
  13. vs2019 无法打开包括文件:“SDKDDKVer.h”: No such file or directory的另外一种解决思路
  14. 降雨量等值线图(一)——底图整饬
  15. 人工智能导论——智能计算(进化算法+群智能优化)
  16. html文件超链接打不开,Excel中出现超链接打不开的解决方法
  17. 电脑主板线路连接图解_台式机电源线接法图解(电脑主板接线图解高清
  18. 五一劳动节,讲讲NEO智能合约的调试
  19. [bzoj4540][莫队算法]序列
  20. 如何评价微软在数据中心使用FPGA代替传统CPU的做法?

热门文章

  1. MyBatis之使用XML配置SQL映射(一)
  2. window和document对象
  3. [渝粤教育] 武汉理工大学 数字信号处理 参考 资料
  4. 【渝粤教育】国家开放大学2018年秋季 0700-22T中级会计实务(一) 参考试题
  5. 23种设计模式(五)单一职责之装饰模式
  6. Python进阶(一)Python中的内置函数、内置方法、私有属性和方法详解
  7. 数学方面的能力该怎么培养
  8. Instruments工具的使用
  9. 【转】郭敬明作品中100句经典的话
  10. js排序算法05——快速排序