GCD解析

2019-08-08  本文已影响0人  konglei
线程池

死锁(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

GCD源码分析

iOS开发中的11种锁以及性能对比

上一篇 下一篇

猜你喜欢

热点阅读