• 关于GCD使用


      在各种书籍资料中看到关于GDC中容易死锁的调用

    一、

    -(void)test{

      dispatch_sync(dispatch_get_main_queue(), ^{NSLog(@"Hello World");});

    }

    这样的调用会造成死锁,但是没解释清楚为什么不能这样调用。下面就以来说明原因:

    由于主队列是先进先出,等待上一个结束才能执行下一个任务.在主线程中调用test函数,这样test就会进入主队列中这个步骤叫A,当在主队列中执行dispatch_sync(dispatch_get_main_queue(), ^{NSLog(@"Hello ?");});的时候又会往主队列中加入一个任务这个任务叫B,由于在队列中A还没有执行完所以B要等待A

    执行完才能执行,但是A要执行完要先执行完B任务,这样就造成互相等待出现死锁。

    1 主线程执行test函数(A操作)

    2 将A加入主队列

    3 在执行A的时候又调用了dispatch_sync函数(B操作)将B加入主队列

    4  这样主队列中就有 B-A两个任务

    5 由于A一直没有执行完不能出队列(因为B执行完A才能出队列, 然而B在队列中根本没执行因为根据先进先出的规则A先进队列,所以B排在A后面执行)

    所以就造成互相等待造成死锁。

     

    二、

     

    -(void)testThread{

        dispatch_queue_t queue = dispatch_get_main_queue();

        dispatch_async(queue, ^{

            dispatch_sync(dispatch_get_main_queue(), ^{

                NSLog(@"1");

            });

         });

        NSLog(@"ok");

    }

    在object-c高级编程中这个调用也会死锁。参考一下列表

     

    这里都是用的主队列,虽然用的是异步函数,但是根据上表主队列都是在主线程中执行的,所以参考第一个列子也很容易得出死锁的原因

    如果将主队列换成全局队列或是手动创建队列则不会出现死锁。 

     

    三、

     

    -(void)testThread2{

         dispatch_queue_t queue = dispatch_queue_create("com.hype.threadtest", NULL);

             dispatch_async(queue, ^{

             dispatch_sync(queue, ^{

                 NSLog(@"1");

            });

         });

         NSLog(@"ok");

     }

    这样调用虽然没出现死锁但是NSLog(@"1")却没有执行,原因不清楚,有待研究。

     

    总结:如果要避免出现死锁,那么绝对不要给运行在同一队列中得任务调用 dispatch_sync或是 dispatch_sync_f函数

    四、

    dispatch_queue_t queue = dispatch_queue_create("com.liancheng.serial_queue", DISPATCH_QUEUE_SERIAL);
     
    dispatch_async(queue, ^{
        // 到达串行队列
         
        dispatch_sync(queue, ^{     //发生死锁
         
        });
    });

    dispatch_sync需要等待block执行完成,同时由于队列串行,block的执行需要等待前面的任务,也就是dispatch_sync执行完成。两者互相等待,永远也不会执行完成,死锁就这样发生了

    从这里看发生死锁需要2个条件:

    1. 代码运行的当前队列是串行队列

    2. 使用sync将任务加入到自己队列中

    如果queue是并行队列,或者将任务加入到其他队列中,这是不会发生死锁的。

    五 、

    不管在哪个线程中只要使用了dispatch_get_main_queue()队列都会转到主线程中去执行

        dispatch_queue_t globalQueue = dispatch_queue_create("com.liancheng.global_queue", DISPATCH_QUEUE_SERIAL);

        dispatch_async(globalQueue, ^{

            NSLog(@"current thread1:%@", [NSThread currentThread]);

            dispatch_async(dispatch_get_main_queue(), ^{

                   NSLog(@"current thread2:%@", [NSThread currentThread]);

            });

            NSLog(@"current thread3:%@", [NSThread currentThread]);

        });

        NSLog(@"this is main queue:%@ ", [NSThread currentThread]);

     

  • 相关阅读:
    LeetCode 811. Subdomain Visit Count (子域名访问计数)
    LeetCode 884. Uncommon Words from Two Sentences (两句话中的不常见单词)
    LeetCode 939. Minimum Area Rectangle (最小面积矩形)
    LeetCode 781. Rabbits in Forest (森林中的兔子)
    LeetCode 739. Daily Temperatures (每日温度)
    三种方式实现按钮的点击事件
    239. Sliding Window Maximum
    14.TCP的坚持定时器和保活定时器
    13.TCP的超时与重传
    12.TCP的成块数据流
  • 原文地址:https://www.cnblogs.com/HypeCheng/p/4500972.html
Copyright © 2020-2023  润新知