iOS GCD 串行和并发队列的理解
2019-05-24 本文已影响0人
大风天上来
首先看串行队列同步异步任务的请求顺序
/**
测试串行队列
*/
- (void)testSerialQueue {
dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
NSLog(@"1 %@", [NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
sleep(5);
NSLog(@"2 %@", [NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"3 %@", [NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"4 %@", [NSThread currentThread]);
});
}
运行结果
串行队列,同步异步任务执行
运行结果显示:任务依次执行,异步会创建新线程。
- 结论:串行队列中的任务以FIFO方式从序列中执行,一次只调度一个任务(无论同步异步,前面任务执行完了,才开启下一个任务),异步任务会创建新的线程(文末的参考链接中,同步异步都在同一个线程执行,初步估计是iOS旧版本的原因,新系统变更的关系)。
看看并行队列异步任务的执行结果
- (void)testSerialQueue {
dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0 ; i < 20; i ++) {
dispatch_async(serialQueue, ^{
NSLog(@"%d %@",i, [NSThread currentThread]);
});
}
}
并行队列,异步任务
从运行结果可以看出,并发会创建多个线程,而且并发队列中的线程是可以重复利用的(线程池)。
并发队列的同步任务
- (void)testSerialQueue {
dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0 ; i < 20; i ++) {
dispatch_sync(serialQueue, ^{
NSLog(@"%d %@",i, [NSThread currentThread]);
});
}
}
并发队列,同步任务
从运行结果可以看出,并发队列的同步任务,没有创建新的线程,都在主线程依次执行
- 并行和并发
- 并发:两个或多个事件在同一时间间隔内发生。同一时间内只有一个任务执行
例如单CPU的处理多线程; - 并行:两个或多个事件在同一时刻发生。同一时间内可能有多个任务执行
例如多CPU的处理多线程;
- 并发:两个或多个事件在同一时间间隔内发生。同一时间内只有一个任务执行
串行队列同步任务的执行顺序
/**
测试串行队列
*/
- (void)testSerialQueue {
dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_SERIAL);
NSLog(@"this is mainQueue-0 %@", [NSThread currentThread]);
dispatch_sync(serialQueue, ^{
NSLog(@"1 %@", [NSThread currentThread]);
});
NSLog(@"this is mainQueue-1 %@", [NSThread currentThread]);
dispatch_sync(serialQueue, ^{
NSLog(@"2 %@", [NSThread currentThread]);
});
NSLog(@"this is mainQueue-2 %@", [NSThread currentThread]);
}
串行队列,同步任务
结论:本来我预测的执行结果是
this is mainQueue-0
this is mainQueue-1
this is mainQueue-2
1
2
因为没有考虑到同步任务会阻塞当前线程。前面提到串行队列中的任务,按照FIFO的方式依次执行。但是如果考虑到阻塞的问题,后面的任务是没有进入队列的。
串行队列 同步任务 嵌套
串行队列,嵌套同步任务,阻塞当前线程,线程陷入死锁。
既阻塞了当前线程、又想在当前线程末尾执行。
执行结果
执行结果分析:嵌套内的同步任务会阻塞当前线程,并且陷入死锁。嵌套内的异步任务不会阻塞当前线程
/**
测试并行队列同步任务 嵌套
*/
- (void)testSerialQueue {
dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"this is mainQueue-0 %@", [NSThread currentThread]);
dispatch_sync(serialQueue, ^{
NSLog(@"1 %@", [NSThread currentThread]);
dispatch_sync(serialQueue, ^{
NSLog(@"inside task %@", [NSThread currentThread]);
});
});
NSLog(@"this is mainQueue-1 %@", [NSThread currentThread]);
dispatch_sync(serialQueue, ^{
NSLog(@"2 %@", [NSThread currentThread]);
dispatch_sync(serialQueue, ^{
NSLog(@"inside task 2 %@", [NSThread currentThread]);
});
});
NSLog(@"this is mainQueue-2 %@", [NSThread currentThread]);
}
并行队列,同步任务
测试并行队列同步任务的执行顺序- 并行队列的同步任务进行嵌套,有阻塞,不会产生死锁
- 同步任务依次按顺序执行
结论:
串行队列,同步任务会阻塞当前线程,嵌套内的同步任务会产生死锁;
参考: