这是我参与8月更文挑战的第15天,活动详情查看: 8月更文挑战
我们结合一道新浪微博的笔试题来进行分析,这里我们针对两种不同情况:
- 并发队列
- 串行队列
并发
新浪微博笔试题,原题如下:
在ABCD四个选项中,选择出哪个选项的打印顺序可能出现?
解析:
- 1、
DISPATCH_QUEUE_CONCURRENT表示队列queue是一个并发队列; - 2、
dispatch_sync(queue, ^{ NSLog(@"3"); })同步函数将会堵塞249行以下的代码,所以3一定比0先打印; 0在主队列中,所以0一定比7 8 9先打印;- 3、因为
NSLog(@"1")和NSLog(@"2")都是异步函数,而且都处在并发队列中,所以1和2的打印顺序是无序的,也就是打印顺序有可能是1先打印,也有可能是2先打印,我们运行看一下打印结果:
结果
3在0之前,1和2的打印顺序不固定;
- 4、我们在
NSLog(@"3")之前添加代码sleep(2);,看一下打印结果:
异步函数处在并发队列中,将会开启线程,在当前线程中执行任务,任务将会异步执行,没有顺序,其调用顺序与CPU的调度有关,说明1 2 3的打印顺序是不固定的,其顺序由CPU调度决定,而不同设备,不同时刻其CPU调度都可能不一样
最终,由于
1 2 3的顺序不固定,但是3一定比0先打印,0一定比7 8 9先打印,7 8 9的顺序也是不固定的,所以最终结果为AC,也就是1230789和3120798两种结果都有可能出现;
串行
请问,在ABCD四个选项中那个打印顺序是对的?
解析:
- 1、
DISPATCH_QUEUE_SERIAL表示队列queue是一个串行队列; - 2、
dispatch_sync(queue, ^{ NSLog(@"3"); })同步函数将会堵塞249行以下的代码,所以3一定比0先打印; - 3、穿行队列的特性
FIFO,也就是先进先出(First In First Out),加入队列的任务将会按照顺序执行,所以2一定在1后边打印;我们可以如下验证一下:
4、我们在
NSLog(1)之前休眠了2秒钟,按照我们正常的逻辑,都是异步函数,因为NSLog(1)休眠了2秒钟,按道理应该先打印2,结果打印顺序,依然是1在前,2在后;这是因为,异步函数加入串行队列之后,将会开启一条新的线程来执行队列中的任务,而队列是串行队列,所以任务将会一个接着一个的顺序执行;
- 5、后边的同理,打印顺序为
7 8 9;
所以,最终打印结果为
1230789,也就是A答案
函数与队列的总结
- 同步函数串行队列
- 不会开启线程,在当前线程执行任务
- 任务串行执行,任务一个接着一个
- 会产生堵塞
- 同步函数并发队列
- 不会开启线程,在当前线程执行任务
- 任务一个接着一个
- 异步函数串行队列
- 开启线程,一条新线程
- 任务一个接着一个
- 异步函数兵法队列
- 开启线程,在当前线程执行任务
- 任务异步执行,没有顺序,与CPU调度有关
相关文章
如果还是对此有疑问的话,可以看我的另外两篇文章对多线程和GCD的介绍: