工作的NSCondition锁

时间:2015-03-04 09:29:02

标签: 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 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

1 个答案:

答案 0 :(得分:3)

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

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

为了正确使用条件变量, 的示例都不正确。重点是要保护谓词的状态。以下示例基于the documentation的伪代码。

NSCondition condvar = [NSCondition new];
__block BOOL workRequired = NO;

// something somewhere else does this at some point ^{
    [condvar lock];
    workRequired = YES;
    [condvar signal];
    [condvar unlock];
};

[condvar lock];

while (!workRequired) {
    [condvar wait];
}

// Do the work
workRequired = NO;
[condvar unlock];

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

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

// Do rest

如果由于某种原因你不知道你是否已经在该队列上运行,那么semaphore就足够了。

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