如何在Grand Central Dispatch中创build一个死锁?

在苹果文档中,它说:

重要提示:您不应该从正在计划传递给该函数的同一队列中执行的任务调用dispatch_sync或dispatch_sync_f函数。 这对保证死锁的串行队列尤为重要,但对于并发队列也应该避免。

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

某个队列上的故意死锁:

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调用到同一个队列中。

造成死锁的简单代码:

 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上运行,但是直到当前块结束才能运行,而当前块又等待内部完成,因为我们同步调用它。

最简单的方法是在当前队列中dispatch_sync同步:

 dispatch_sync(dispatch_get_current_queue(), ^{}); 

当当前队列是一个串行队列,例如主队列时,这会阻塞。

在最新的Swift语法中:

 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 }