Cocoa 条件锁的工作原理

Cocoa 条件锁的工作原理,cocoa,condition-variable,Cocoa,Condition Variable,我最近一直在使用NSCondition,我真的不理解锁定和解锁部分 比如说, NSCondition lock = [NSCondition new]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Do stuff [lock signal]; }; [lock wait]; //Do rest 这很好用。这有什么区别 NSCondition lock

我最近一直在使用NSCondition,我真的不理解锁定和解锁部分

比如说,

NSCondition lock = [NSCondition new];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //Do stuff
    [lock signal];
};

[lock wait];
//Do rest
这很好用。这有什么区别

NSCondition lock = [[NSCondition alloc] init];
[lock lock];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //Do stuff
    [lock signal];
    [lock unlock];
};

[lock wait];
//Do rest

在等待之前,必须先锁定条件变量。 等待释放锁,然后保证阻塞,直到发出信号并重新获取锁为止。请注意,如果多个线程正在等待,则只有一个线程将收到信号通知,其他线程将继续等待进一步的信号。或者,如果谓词在执行后仍为true,则可以向所有线程广播该信号

锁是互斥锁(mutex),这意味着在任何时候只有一个线程可以持有锁。除了使用它来保护您使用条件变量的目的之外,它还保护条件变量的内部工作。如果您试图在没有锁的情况下使用它,那么在跨多个线程检查/设置条件时会出现争用条件

要正确使用条件变量,两个示例都不正确。关键是要保护谓词的状态。这里有一个例子是基于伪代码的

在您的示例中,除了“块已完成”之外,您没有任何条件。在这种情况下,您应该只使用dispatch_sync

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Do stuff
};

// Do rest
如果出于某种原因,您不知道自己是否已经在该队列上运行,那么a就足够了

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0L);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Do stuff
    dispatch_semaphore_signal(semaphore);
};

dispatch_semaphore_wait(semaphore);
// Do rest

除了您注意到的问题之外,OP在一个线程上锁定,在另一个线程上解锁,这是不合法的。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0L);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Do stuff
    dispatch_semaphore_signal(semaphore);
};

dispatch_semaphore_wait(semaphore);
// Do rest