理解 iOS 开发中 GCD 相关的同步(synchronization)\ 异步(asynchronization),串行(serial)\ 并行(concurrency)概念

iOS 开发过程中,常常需要用到多线程技术,GCD 是常用的实现多线程的技术,其因简洁底层而备受欢迎。

GCD 技术中,同步(synchronization)\ 异步(asynchronization),串行(serial)\ 并行(concurrency)等概念常常令人迷惑,不好理解。本文将对这两对概念进行尽可能简单的阐释。

同步和异步是针对当前代码流(即当前线程)和加入队列中的任务之间执行顺序的关系而言的。以同步的方式向队列中添加任务会阻塞当前线程,直到同步到队列中的任务执行完毕返回后,才会接着执行当前的代码流;以异步的方式向队列中添加的任务则不会阻塞当前线程,将任务添加到队列中后,不用等待任务执行完毕,即刻执行当前代码流。举例说明如下:


同步(dispatch_sync):

    dispatch_sync(myQueue,^{
printf("1"); //任务 1
});
printf("2");
dispatch_sync(myQueue,^{
printf("3"); //任务 3
});
printf("4");

上面的代码执行结果只有一种可能,即输出“1234”。

在将输出 1 的任务(即代码中任务 1)同步到队列 myQueue 中后,当前线程阻塞,等待任务 1 执行完毕并返回后(即输出 1 之后),才能接着执行当前线程,输出 2。输出 2 之后,当前代码流继续运行,将任务 3 再同步到队列 myQueue 中后,当前线程阻塞,等待任务 3 执行,输出 3,之后当前代码流继续运行输出 4。

这段代码的输出结果与 myQueue 是串行队列还是并行队列没有关系。


异步(dispatch_async):

    dispatch_async(serialQueue,^{
printf("1"); //任务 1
});
printf("2");
dispatch_async(serialQueue,^{
printf("3"); //任务 3
});
printf("4");

上面代码执行结果可能为 “1234”、“1243”、“2134”、“2143”、“2413” 中的一种,2 始终在 4 前面,1 始终在 3 前面(注意:此例中的队列(serialQueue)为串行队列,串行队列的概念将在后文讲述),2 始终在 3 前面。

将任务 1 异步添加到队列 serialQueue 中之后,不需要等待其执行完毕,当前代码流就继续执行了。当前代码流输出 2 时,可能任务 1 还没执行,也可能执行完毕了,因此 1 可能在 2 前输出也可能在 2 后输出;

同理,将任务 3 异步添加到队列 serialQueue 中之后,不需要等待其执行完毕,当前代码流就继续执行。当前代码流输出 4 时,可能任务 3 还没执行,也可能执行完毕了,因此 3 可能在 4 前输出也可能在 4 后输出。

对于当前代码流,输出 2 一定在 输出 4 前执行,因此 2 必定在 4 前输出。

对于串行队列 serialQueue ,任务 1 一定在 任务 3 前执行,因此 1 必定在 3 前输出。

将任务 3 添加到队列 serialQueue 的操作必定在输出 2 后进行,因此 2 必定在 3 前输出。


串行和并行是针对一个队列中的多个任务执行顺序而言的。串行队列是指队列中的任务是一个接一个地执行的,队首的任务执行完毕后才能执行其后面的任务,直至执行队尾的任务;并行队列是指队列中的任务可以并发地执行,即开始执行队首的任务后,不必等其执行完毕就可以接着开始执行队首之后的任务,因此在某一时刻可能存在同时执行的多个任务。

创建串行队列的方法是:

 dispatch_queue_t serialQueue = dispatch_queue_create("mySerialQueue", NULL); 

或

 dispatch_queue_t serialQueue = dispatch_queue_create("mySerialQueue", DISPATCH_QUEUE_SERIAL);

同时主线程的队列也是串行队列,获取方法:

dispatch_queue_t mainQueue = dispatch_get_main_queue();

创建并行队列的方法是:

dispatch_queue_t concurrentQueue = dispatch_queue_create("myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);

同时系统提供了获取系统并发队列的函数:

dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);

第一个参数 identifier 的值宏定义可以为

DISPATCH_QUEUE_PRIORITY_HIGH、

DISPATCH_QUEUE_PRIORITY_DEFAULT、

DISPATCH_QUEUE_PRIORITY_LOW、

DISPATCH_QUEUE_PRIORITY_BACKGROUND,

四个参数值获取的并发队列优先级依次从高到低;第二个参数 flags为系统保留参数,应传入值 0。


混淆同步异步和并行串行的概念,是因为我们没有弄清楚它们分别针对的对象是什么,一旦明白了它们描述的对象的区别,就不会在混淆了。再次总结一下,同步异步描述的是当前线程或代码流是否要阻塞以等待加入队列的任务执行完毕:同步要阻塞当前线程;异步不会阻塞当前线程。串行和并行描述的时队列里各个任务是否可以并发执行:串行队列里的任务不能并发执行,只能一个接一个地执行,同一时刻该串行队列里的任务最多只有一个在执行;并发队列里的任务后面的任务不必等待前面的任务执行完毕再执行,可以多个同时执行,同一时刻该并行队列里的任务可以有多个正在执行。

iOS:转载:同步、异步、并行、串行的详解的更多相关文章

  1. iOS:GCD理解1(同步-异步、串行-并行)

    1.并行-异步(ST1与ST2抢占资源) 1-1).获取 并行(全局)队列 ,DISPATCH_QUEUE_PRIORITY_DEFAULT 为默认优先级. dispatch_queue_t queu ...

  2. iOS GCD NSOperation NSThread等多线程各种举例详解

    废话就不多说,直接上干货.如下图列举了很多多线程的知识点,每个按钮都写有对应的详细例子,并对运行结果进行分析,绝对拿实践结果来说话.如果各位道友发现错误之处还请指正.附上demo下载地址

  3. 【原】iOS多线程之异步任务+并行队列情况与异步任务+串行队列(主队列)情况

    异步任务+并行队列 把异步任务放到并行队列进行执行,异步任务会在不同的线程中执行. /*异步执行+并行队列*/ - (IBAction)clickBasic1:(UIButton *)sender { ...

  4. VLC命令行参数详解

    VLC命令行参数详解 2012-11-29 14:00 6859人阅读 评论(0) 收藏 举报 Usage: vlc [options] [stream] ...You can specify mul ...

  5. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  6. 转:MySQL Row Format(MySQL行格式详解)

    MySQL Row Format(MySQL行格式详解) --转载自登博的博客

  7. 李洪强iOS经典面试题155 - const,static,extern详解(面试必备)

    李洪强iOS经典面试题155 - const,static,extern详解(面试必备) 一.const与宏的区别(面试题): const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽 ...

  8. appledoc导出iOS代码文档的使用和问题详解(干货篇)

    appledoc导出iOS代码文档的使用和问题详解(干货篇) 1. 简单说一下背景和自己感受 背景: 项目好像突然黄了,公司让详细写项目代码的注释并且导出文档,弄完之后就要封版. 说实话:听到这个消息 ...

  9. iOS GCD, 同步,异步,串行队列,并行队列,dispatch_group

    同步,指代码在同一个线程运行 异步,代码在另一个线程运行 串行队列,提交到该队列的block会顺序执行 并行队列,提交到该队列的block会并发执行 如果想等某一队列中所有block都执行完了在执行一 ...

随机推荐

  1. Leetcode 之Binary Tree Preorder Traversal(42)

    树的先序遍历.定义一个栈,先压入中间结点并访问,然后依次压入右.左结点并访问. vector<int> preorderTraversal(TreeNode *root) { vector ...

  2. 关于HTML,css3自适应屏幕,自适应宽度

    设置了在不同分辨率下,显示的css样式: @media screen and (min-width:1080px){ .box{ width: 1080px;}.content{width: 1040 ...

  3. window,getComputedStyle,letter-spacing

       js 拿到element的css样式    window.getComputedStyle(ele,[pseuso)    比如想拿到一个element的背景色 window.getComput ...

  4. redis之(六)redis的列表类型的命令

    [一]向列表两端添加元素 -->命令:LPUSH key value [value ...] -->向列表的左侧添加元素,返回值表示增加元素后列表的长度 -->命令:RPUSH ke ...

  5. Decode Ways——动态规划

    A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...

  6. mybatis官网学习

    javaType:一个 Java 类的完全限定名,或一个类型别名(参考上面内建类型别名 的列表) .如果你映射到一个 JavaBean,MyBatis 通常可以断定类型. 然而,如果你映射到的是 Ha ...

  7. sqlserver 构架与性能优化

    太阳底下没有新鲜事 一.sqlserver 构架结构 1.查询优化器三阶段 1).找计划缓存如果找到直接使用 2).简单语句生成0开销的执行计划 3).正式优化 一般情况下优化到开销小于1.0就会停止 ...

  8. JDBC连接执行mysql存储过程报权限错误:User does not have access to metadata required to determine stored procedure parameter types. If rights can not be granted,

    分析:JDBC在调用存储过程时不光用户要有execute的权限,还需要对mysql.proc具有访问权限.否则它无法访问metadata 解决方案:给数据库用户赋权,赋执行mysql.proc表的se ...

  9. rsync数据定时增量备份知识管理服务器数据

    为了保证公司知识管理服务器数据的安全性,所以计划每天同步confluence服务器上面数据 一.安装rsync服务端 1.查看是否安装rsync ps -ef | grep rsync 2.添加配置文 ...

  10. Win7 + VirtualBox + CentOS(无桌面), 扩容

    http://www.2cto.com/os/201401/269730.html 对于目前的网络开发者来说,比较好的搭档就是Win7+VirtualBox+CentOS的组合,既可以发挥Linux强 ...