美文网首页
iOS多线程学习小记『GCD的API之dispatch_sync

iOS多线程学习小记『GCD的API之dispatch_sync

作者: 达若漠沙 | 来源:发表于2018-07-24 19:20 被阅读88次

    3.2.8 dispatch_sync

    dispatch_async 函数的“async”意味着 “非同步”(asynchronous)就是将指定的Block”非同步”地追加到指定的Dispatch Queue中,dispatch_async函数不做任何等待。

    Dispatch_async函数的处理流程

    既然有“async”当然也就有“sync”,即 dispatch_sync函数。它意味着“同步”(synchronous)也就是将指定的Block”同步”追加到指定的Dispatch Queue中。在追加Block结束之前,dispatch_sync函数会一直等待。


    Dispatch_sync函数的处理流程

    如 dispatch_group_wait函数中的说明,“等待”意味着当前线程停止。

    • 我们先假设这样一种情况:执行Main Dispatch Queue 时,使用另外的线程Global Dispatch Queue进行处理,处理结束后立即使用所得到的结果。在这种情况下就要使用dispatch_sync函数。
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_sync(queue, ^{
            NSLog(@"同步执行");
        });
        
    
    • 一旦调用dispatch_sync函数,那么在指定的处理执行结束之前,改函数不会返回。dispatch_sync函数可以简化源代码,也可以说是简易版的dispatch_group_wait函数。

    • 正因为dispatch_sync函数使用简单,所以也容易引起问题,即死锁

    例如 如果在主线程中执行以下源代码就会死锁。

        //在Main Dispatch Queue 即主线程中执行指定的Block,并等待期执行结束。而其实在主线程中正在执行这些代码。所以无法将Block追加到Main Dispatch Queue中,导致死锁。
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"Hello?");
        });
    
    • 在Main Dispatch Queue 即主线程中执行指定的Block,并等待期执行结束。而其实在主线程中正在执行这些代码。所以无法将Block追加到Main Dispatch Queue中,导致死锁。
        //Main Dispatch Queue 中执行的Blcok等待 Main Dispatch Queue 中要执行的Block执行结束。这样的思索就像是在画像上画画一样。
        dispatch_async(dispatch_get_main_queue(), ^{
            dispatch_sync(dispatch_get_main_queue(), ^{
                NSLog(@"hello?");
            });
        });
    
    • Main Dispatch Queue 中执行的Blcok等待 Main Dispatch Queue 中要执行的Block执行结束。这样的思索就像是在画像上画画一样。

    • 当然Serial Dispatch Queue 也会因此相同的问题。

        //因为 queue2为串行队列 ,执行同步操作,那么需要等待其当前任务执行完毕,
        //串行队列异步任务—>嵌套同步任务—>导致当前线程死锁.
        //因为CPU执行到53行时,因为是同步任务,需要等待当前线程(目前是子线程)任务执行完,也即是51行外层嵌套的子线程的异步任务.由于外层嵌套的子线程异步任务执行时又要等待53行的同步任务执行完,所以导致相互等待,死锁.
        //https://www.jianshu.com/p/c5ee8ba01993
        dispatch_queue_t queue2 = dispatch_queue_create("com.examle.gcd.MySerialDispatchQueue", NULL);
        dispatch_async(queue2, ^{
            NSLog(@"%@",[NSThread currentThread]);
            dispatch_sync(queue2, ^{
                NSLog(@"Hello?");
            });
        });
    
    • 另外,由 dispatch_barrier_async 函数中含有async可推测出,相应的也有dispatch_barrier_sync函数。dispatch_barrier_async函数的作用是在等待追加的处理全部执行结束后,再追加处理到Dispatch Queue 中,此外,它还与dispatch_sync函数相同,会等待追加的处理执行结束。

    参考博文:
    GCD死锁情况

    相关文章

      网友评论

          本文标题:iOS多线程学习小记『GCD的API之dispatch_sync

          本文链接:https://www.haomeiwen.com/subject/fqvymftx.html