死锁(Deadlock)
dispatch_async :底层运用了线程池,会在和当前线程不同的线程上处理任务。
dispatch_sync :一般不会新开启线程,而是在当前线程执行任务(比较特殊的是main queue,它会利用main runloop
将任务提交到主线程来执行),同时,它会阻塞当前线程,等待提交的任务执行完毕。当target queue是并发线程时,会直接执行任务。
而target queue是串行队列时,会检测当前线程是否已经拥有了该串行队列,如果答案是肯定的,则会触发crash,
这与老版本GCD中会触发死锁不同,因为在新版GCD中,已经加入了这种死锁检测机制,从而触发crash,避免了调试困难的死锁的发生。
如下所示,当我们在同一线程中的串行队列任务执行期间,再次向该队列提交任务时,会引发crash。
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"dispatch_async %@",[NSThread currentThread]);
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"dispatch_sync %@",[NSThread currentThread]);
});
});
在
串行队列中
,当前队列的调度块内(包含嵌套)调用当前队列
的同步任务
会死锁
异步调度块要等自己调度块内执行完成才能继续
同步调度块要等当前队列添加的的任务(异步调度块)结束,自己才能阻塞当前队列,执行当前调度块
互相等待,造成死锁
导致死锁原因, 互斥条件:一个资源每次只能被一个进程使用。请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
临界区(Critical Section)
就是一段代码不能被并发执行,也就是,两个线程不能同时执行这段代码。这很常见,因为代码去操作一个共享资源,例如一个变量若能被并发进程访问,那么它很可能会变质(它的值不再可信)。
static NSString *_name;
static dispatch_queue_t _concurrentQueue;
@implementation ZYPerson
- (instancetype)init
{
if (self = [super init]) {
_concurrentQueue = dispatch_queue_create("com.person.syncQueue", DISPATCH_QUEUE_CONCURRENT);
}
return self;
}
- (void)setName:(NSString *)name
{
dispatch_barrier_async(_concurrentQueue, ^{
_name = [name copy];
});
}
- (NSString *)name
{
__block NSString *tempName;
dispatch_sync(_concurrentQueue, ^{
tempName = _name;
});
return tempName;
}
@end
在这个代码中,我用了
dispatch_barrier_async
,可以翻译成栅栏(barrier),它可以往队列里面发送任务(块,也就是block),这个任务有栅栏(barrier)的作用。
在队列中,barrier块必须单独执行,不能与其他block并行。这只对并发队列有意义,并发队列
如果发现接下来要执行的block是个barrier block
,那么就一直要等到当前所有并发的block都执行完毕
,才会单独执行
这个barrier block代码块,等到这个barrier block执行完毕,再继续正常处理其他并发block。在上面的代码中,setter方法中使用了barrier block以后,对象的读取操作依然是可以并发执行的
,但是写入操作就必须单独执行了
。
讲的应用场景
Grand Central Dispatch Tutorial for Swift 4: Part 1/2
Grand Central Dispatch Tutorial for Swift 4: Part 2/2
iOS开发:深入理解GCD 第一篇
iOS开发:深入理解GCD 第二篇(dispatch_group、dispatch_barrier、基于线程安全的多读单写)
GCD源码分析
新版
Cooci的
GCD源码分析(一)
Cooci的
GCD源码分析(二)
Cooci的
GCD视频
老版
GCD源码吐血分析(1)——GCD Queue
GCD源码吐血分析(2)——dispatch_async/dispatch_sync/dispatch_once/dispatch group
网友评论