618 字
3 分钟
任务与队列的几个面试题
一、 我们先看个面试题热热身
面试题一 - 串行队列
下面的打印输出会是什么样?
/// 串行队列dispatch_queue_t queue = dispatch_queue_create("Ryukie.Queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{ NSLog(@"1");});
dispatch_async(queue, ^{ NSLog(@"2");});
dispatch_sync(queue, ^{ NSLog(@"3");});
NSLog(@"0");
dispatch_async(queue, ^{ NSLog(@"7");});
dispatch_async(queue, ^{ NSLog(@"8");});
dispatch_async(queue, ^{ NSLog(@"9");});- A: 1230789
- B: 1237890
- C: 3120789
- D: 2137890
分析
3的同步任务,阻碍了0 7 8 9的异步任务,故3一定在0 7 8 9前。7 8 9三个任务的顺序不一定,但在0之后。1 2 3的顺序不一定。
满足上面几点的答案为:A C
这里很可能会觉得
12一定在3之前,要清楚3阻塞的是3之后的任务,123的顺序并不一定。
如果是异步队列呢?
123 789 都是乱序的
面试题二 - while
输出会是多少呢?
__block int num = 0;
while (num < 10) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ num++; });}
printf("%d\n", num);- 由于 num++ 是异步的,所以执行的次数大于等于 10
- 由于 while 循环条件阻塞,打印一定在 num >= 10 条件下输出
- 输出大于等于 10

面试题三 - for
输出会是多少呢?
__block int num = 0;
for (int i = 0; i < 1000; i++) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ num++; });}
printf("%d\n", num);- for 循环保证了循环次数,一定是1000次
- for循环不会阻塞后面的 printf 函数执行
- 故:打印结果小于等于 1000(可能打印的时候还有 ++ 任务未执行完)

面试题三 - 死锁
下面几个分别输出是什么
- (void)deadLock1 { // dispatch_queue_t queue = dispatch_queue_create("Ryukie", NULL); dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_SERIAL); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_sync(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5");}- 输出
- 1,5,2 死锁
- 分析
- 串行队列
- async 放入队列一个 blockA 任务
- blockA 内部又向队列内部添加了一个 blockB 任务
- 队列需要等待 blockA 执行完毕再执行下一个任务
- 但是添加 blockB 时,sync 阻断了 blockA 内部的执行,导致 blockA 无法执行完成
- 所以死锁了
- (void)deadLock2 { dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_CONCURRENT); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_sync(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5");}- 输出
- 1,5,2,3,4
- (void)deadLock3 { // dispatch_queue_t queue = dispatch_queue_create("Ryukie", NULL); dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_SERIAL); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_sync(queue, ^{ NSLog(@"3"); }); }); NSLog(@"5");}- 输出
- 1,5,2 死锁
- 和第一个一样
- (void)deadLock4 { dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_SERIAL); NSLog(@"1"); NSLog(@"2"); dispatch_sync(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); NSLog(@"5");}- 输出
- 1,2,3,4,5
- 串行队列
- 同步任务,没有阻塞队列内任务的执行,没有死锁,正常执行
- 所以 同步任务 + 串行队列 不一定死锁
二、 任务与队列
