小心串行队列的执行依赖
小心串行队列的执行依赖
概念
什么是串行
任务串行,意味着在同一时间,有且只有一个任务被执行,即一个任务执行完毕之后再执行下一个任务。
请听题
下面的 Objective-C
代码执行结果是?
dispatch_queue_t serialQueue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_async(serialQueue, ^{
NSLog(@"2");
});
NSLog(@"3");
dispatch_sync(serialQueue, ^{
NSLog(@"4");
});
NSLog(@"5");
分析
运行结果如下
1
3
2
4
5
- 首先先打印
1
- 接下来将任务
2
添加至串行队列中,由于任务2
是异步执行的(会开新的线程),不会阻塞当前线程,所以继续向下执行,打印3
- 然后是任务
4
,将任务4
添加至串行队列上,因为任务4
和任务2 在同一串行队列,故任务
4必须等任务
2执行完后才能执行,又因为任务
4是同步任务,会阻塞当前线程,只有执行完任务
4才能继续向下执行打印
5`
所以最终顺序就是 13245 - 这里的任务
4
在主线程中执行,而任务2
在子线程中执行, 可以添加线程相关信息, 如下
dispatch_queue_t serialQueue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
NSLog(@"1, at %@", [NSThread currentThread]);
dispatch_async(serialQueue, ^{
NSLog(@"2, at %@", [NSThread currentThread]);
});
NSLog(@"3, at %@", [NSThread currentThread]);
dispatch_sync(serialQueue, ^{
NSLog(@"4, at %@", [NSThread currentThread]);
});
NSLog(@"5, at %@", [NSThread currentThread]);
运行结果如下
1, at <_NSMainThread: 0x600001710000>{number = 1, name = main}
3, at <_NSMainThread: 0x600001710000>{number = 1, name = main}
2, at <NSThread: 0x600001758200>{number = 7, name = (null)}
4, at <_NSMainThread: 0x600001710000>{number = 1, name = main}
5, at <_NSMainThread: 0x600001710000>{number = 1, name = main}
如果是并发线程呢 ?
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1, at %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"2, at %@", [NSThread currentThread]);
});
NSLog(@"3, at %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"4, at %@", [NSThread currentThread]);
});
NSLog(@"5, at %@", [NSThread currentThread]);
因为是并发线程, 所以任务 2
和任务 4
执行先后的依赖关系, 运行结果有如下3种可能
结果一
1, at <_NSMainThread: 0x600001700100>{number = 1, name = main}
3, at <_NSMainThread: 0x600001700100>{number = 1, name = main}
4, at <_NSMainThread: 0x600001700100>{number = 1, name = main}
2, at <NSThread: 0x600001705700>{number = 5, name = (null)}
5, at <_NSMainThread: 0x600001700100>{number = 1, name = main}
结果二
1, at <_NSMainThread: 0x600001704680>{number = 1, name = main}
3, at <_NSMainThread: 0x600001704680>{number = 1, name = main}
2, at <NSThread: 0x60000174d080>{number = 5, name = (null)}
4, at <_NSMainThread: 0x600001704680>{number = 1, name = main}
5, at <_NSMainThread: 0x600001704680>{number = 1, name = main}