【发布时间】:2013-10-29 22:11:00
【问题描述】:
我有一个包含一些方法的 Objective-c 类,它使用 GCD 队列来确保对资源的并发访问是串行发生的(执行此操作的标准方法)。
其中一些方法需要调用同一类的其他方法。所以锁定机制需要是可重入的。有标准的方法吗?
起初,我使用了这些方法中的每一个
dispatch_sync(my_queue, ^{
// Critical section
});
同步访问。如您所知,当其中一个方法调用另一个这样的方法时,会发生死锁,因为 dispatch_sync 调用会停止当前执行,直到执行另一个块,这也无法执行,因为队列上的执行已停止。为了解决这个问题,我使用了例如这个方法:
- (void) executeOnQueueSync:(dispatch_queue_t)queue : (void (^)(void))theBlock {
if (dispatch_get_current_queue() == queue) {
theBlock();
} else {
dispatch_sync(queue, theBlock);
}
}
在我的每一种方法中,我都使用
[self executeOnQueueSync:my_queue : ^{
// Critical section
}];
我不喜欢这个解决方案,因为对于每个具有不同返回类型的块,我需要编写另一个方法。此外,这个问题在我看来很常见,我认为应该有一个更好的标准解决方案。
【问题讨论】:
-
您是否考虑改用
@synchronized? -
@MartinR,是的,但是
@synchronized是一个经典的锁,不是基于 GCD/队列,因此,据我了解,出于代码简单性和性能的原因,不鼓励使用它.因此,这个问题的标题具有误导性,因为它包含“锁定”。我的意思是以可重入方式与 GDC/队列同步访问。我没有比说“可重入锁定”更好的词了,因为这是大多数人都知道的问题的解决方案的名称。 -
@MartinR,此外,尽管
@synchronized具有为可重入-whatever- 带来更简单代码的优势(如何最好地调用它?)。不过,它背后的锁定机制的性能不如 GCD 队列背后的机制。
标签: objective-c locking grand-central-dispatch reentrantlock