Dan*_* S. 7 locking objective-c grand-central-dispatch reentrantlock
我有一个带有一些方法的objective-c类,它使用GCD队列来确保对资源的并发访问是串行进行的(标准方法是这样做).
其中一些方法需要调用同一类的其他方法.因此锁定机制需要重新进入.有没有标准的方法来做到这一点?
起初,我使用了这些方法
dispatch_sync(my_queue, ^{
// Critical section
});
Run Code Online (Sandbox Code Playgroud)
同步访问.如您所知,当其中一个方法调用另一个此类方法时,会发生死锁,因为dispatch_sync调用会停止当前执行,直到执行其他块,这也无法执行,因为队列上的执行已停止.为了解决这个问题,我然后使用了这种方法:
- (void) executeOnQueueSync:(dispatch_queue_t)queue : (void (^)(void))theBlock {
if (dispatch_get_current_queue() == queue) {
theBlock();
} else {
dispatch_sync(queue, theBlock);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的每个方法中,我都使用
[self executeOnQueueSync:my_queue : ^{
// Critical section
}];
Run Code Online (Sandbox Code Playgroud)
我不喜欢这个解决方案,因为对于每个具有不同返回类型的块,我需要编写另一个方法.此外,这个问题对我来说非常普遍,我认为应该存在一个更好的标准解决方案.
ipm*_*mcc 12
首先要做的事情dispatch_get_current_queue()是:已弃用.现在将使用规范方法dispatch_queue_set_specific.一个这样的例子可能看起来像:
typedef dispatch_queue_t dispatch_recursive_queue_t;
static const void * const RecursiveKey = (const void*)&RecursiveKey;
dispatch_recursive_queue_t dispatch_queue_create_recursive_serial(const char * name)
{
dispatch_queue_t queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
dispatch_queue_set_specific(queue, RecursiveKey, (__bridge void *)(queue), NULL);
return queue;
}
void dispatch_sync_recursive(dispatch_recursive_queue_t queue, dispatch_block_t block)
{
if (dispatch_get_specific(RecursiveKey) == (__bridge void *)(queue))
block();
else
dispatch_sync(queue, block);
}
Run Code Online (Sandbox Code Playgroud)
这种模式非常实用,但可以说它不是防弹的,因为你可以创建嵌套的递归队列dispatch_set_target_queue,并且尝试将内部队列中的工作排入内部队列中将会死锁,即使你已经"在锁内"(在嘲笑引用,因为它看起来只是一个锁,它实际上是不同的:一个队列 - 因此问题,对吗?)外部的.(您可以通过打包dispatch_set_target_queue和维护自己的带外目标图等来解决这个问题,但这仍然是读者的练习.)
你继续说:
我不喜欢这个解决方案,因为对于每个具有不同返回类型的块,我需要编写另一个方法.
这种"状态保护串行队列"模式的一般概念是你保护私有状态; 你为什么要"把自己的队列"带到这个?如果它是关于共享状态保护的多个对象,那么给它们一个固有的方法来查找队列(即,在初始时将其推入,或者将其放在所有相关方都可以访问的地方).目前尚不清楚"自带队列"在这里有用.
| 归档时间: |
|
| 查看次数: |
1742 次 |
| 最近记录: |