在Apple文档中,它说:
重要提示:您永远不应该调用dispatch_sync或dispatch_sync_f 从您在同一队列中执行的任务中运行 计划传递给函数。这对于特别重要 串行队列,保证死锁,但也应该是 避免并发队列。
你如何编写代码才能做到这一点?
答案 0 :(得分:30)
某个队列上的故意死锁:
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
调用到同一队列。
答案 1 :(得分:13)
创建死锁的简单代码:
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
上运行,但是在当前块完成之前它不能运行,而当前块在内部完成,因为我们同步调用它。
答案 2 :(得分:7)
最简单的阻止方法是在当前队列上dispatch_sync
:
dispatch_sync(dispatch_get_current_queue(), ^{});
当当前队列是串行队列时阻塞,例如主队列。
答案 3 :(得分:4)
In latest Swift syntax:
self.navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
答案 4 :(得分:1)
采访者经常会问:“造成僵局的最简单方法是什么?”
的OBJ-C:
dispatch_sync(dispatch_get_main_queue(), ^{});
夫特:
DispatchQueue.main.sync {}
从主线程调用sync
将导致死锁,因为主队列是一个串行队列,sync
停止当前队列执行,直到传递阻塞/闭包完成。
答案 5 :(得分:1)
如果有人感到好奇,并且如果调用sync
以同一队列为目标,则并发队列不会死锁。我知道这很明显,但是我需要确认只有串行队列的行为如此
作品:
let q = DispatchQueue(label: "myQueue", attributes: .concurrent)
q.async {
print("work async start")
q.sync {
print("work sync in async")
}
print("work async end")
}
q.sync {
print("work sync")
}
print("done")
失败:
将q
初始化为let q = DispatchQueue(label: "myQueue") // implicitly serial queue
答案 6 :(得分:0)
在Swift 4.2中,您可以使用以下代码导致死锁:
let aSerialQueue = DispatchQueue(label: "my.label")
aSerialQueue.sync {
// The code inside this closure will be executed synchronously.
aSerialQueue.sync {
// The code inside this closure should also be executed synchronously and on the same queue that is still executing the outer closure ==> It will keep waiting for it to finish ==> it will never be executed ==> Deadlock.
}
}
答案 7 :(得分:0)
在我的情况下,调度队列在Xcode中调用异常或在设备上崩溃,但是 sleep()的使用更适合我的测试目的(只是冻结)当前队列)。
const [cont, setCont] = useState([]);