我在performBlockAndWait 文档中发现了类似这样的内容:
This method may safely be called reentrantly.
我的问题是这是否意味着它永远不会导致死锁,例如会像在单个上下文中那样调用它吗?:
NSManageObjectContext *context = ...
[context performBlockAndWait:^{
// ... some stuff
[context performBlockAndWait:^{
}];
}];
Best Answer-推荐答案 strong>
您可以使用一小段代码自行尝试 ;)
但确实,它不会死锁。
我怀疑,内部实现使用队列特定 token 来识别代码执行的当前队列(参见 dispatch_queue_set_specific 和 dispatch_queue_get_specific )。
如果它确定当前正在执行的代码在它自己的私有(private)队列或子队列上执行,它会简单地绕过同步提交 block ——这会导致死锁,而是直接执行它。
一个可能的实现如下所示:
func executeSyncSafe(f: () -> ()) {
if isSynchronized() {
f()
} else {
dispatch_sync(syncQueue, f)
}
}
func isSynchronized() -> Bool {
let context = UnsafeMutablePointer<Void>(Unmanaged<dispatch_queue_t>.passUnretained(syncQueue).toOpaque())
return dispatch_get_specific(&queueIDKey) == context
}
队列可以这样创建:
private var queueIDKey = 0 // global
init() {
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
QOS_CLASS_USER_INTERACTIVE, 0))
let context = UnsafeMutablePointer<Void>(Unmanaged<dispatch_queue_t>.passUnretained(syncQueue).toOpaque())
dispatch_queue_set_specific(syncQueue, &queueIDKey, context, nil)
}
dispatch_queue_set_specific 将一个token(这里是context - 它只是队列的指针值)与某个key 该队列。稍后,您可以尝试为指定 key 的任何队列检索该 token ,并检查当前队列是同一队列还是子队列。如果是这样,则绕过对队列的调度,而是直接调用函数 f 。
关于ios - 单线程调用两次performBlockAndWait是否会导致死锁?,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/35577556/
|