城之内

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  在各种书籍资料中看到关于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]);

 

 

posted on 2015-05-13 16:59  城之内  阅读(231)  评论(0编辑  收藏  举报