2013-03-13 69 views
13

在苹果的文档,它说:如何在Grand Central Dispatch中创建死锁?

要点:你不应该叫dispatch_sync或从在同一队列执行任务dispatch_sync_f 功能,你是 规划传递给函数。这对保证死锁的 串行队列尤为重要,但对于并发队列也应避免 。

你如何编写代码来做到这一点?

创建
+0

你想例如,创建死锁的代码? – Vladimir 2013-03-13 09:23:36

+0

是的请为学习 – BlackMouse 2013-03-13 09:28:35

+1

另请参见[这个问题](http://stackoverflow.com/questions/10330679/how-to-dispatch-on-main-queue-synchronously-without-a-deadlock)为一个现实的例子那很容易出现死锁。 – zoul 2013-03-13 09:42:37

回答

20

的在某个队列故意僵局:

dispatch_queue_t queue = dispatch_queue_create("my.label", DISPATCH_QUEUE_SERIAL); 
dispatch_async(queue, ^{ 
    dispatch_sync(queue, ^{ 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    }); 

    // this will never be reached 
}); 

很明显,这里说的外部和内部的块在同一个队列操作。发生这种情况的大多数情况是在那些不太明显dispatch_sync的调用者正在操作的队列中的哪个位置。这通常发生在一个(深)嵌套堆栈中,在这个堆栈中,您正在某个队列中初始启动的某个类中执行代码,并且偶然会将dispatch_sync调用到同一个队列中。

+0

当发生死锁时...... UI不应该没有反应? – BlackMouse 2013-03-13 09:46:58

+2

@ user1251004只有在主队列被阻塞的情况下。 – 2013-03-13 09:49:13

+2

在这个例子中,只有创建的'queue'被阻塞。主队列继续运行。 – 2013-03-13 10:04:15

7

简单的代码僵局:

dispatch_queue_t q = dispatch_queue_create("deadlock queue", DISPATCH_QUEUE_SERIAL); 

NSLog(@"1"); 
dispatch_async(q, ^{ 
    NSLog(@"2"); 
    dispatch_sync(q, ^{ 
     NSLog(@"3"); 
    }); 
    NSLog(@"4"); 
}); 
NSLog(@"5"); 

日志输出:

1 
5 
2 

这里内部块定于串行队列q运行,但它不能运行,直到当前块已经结束了,当前块反过来等待内部完成,因为我们同时调用它。

4

到块的最简单方法是将dispatch_sync在当前队列:

dispatch_sync(dispatch_get_current_queue(), ^{}); 

此块在当前队列是一个串行队列,例如主队列。

0

在最新斯威夫特语法:

let queue = DispatchQueue(label: "label") 
queue.async { 
    queue.sync { 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    } 
    // this will never be reached 
} 
相关问题