我需要保护代码的关键区域,该区域是多线程的。我想防止在另一个线程完成之前多次调用它。这就是我正在处理的内容:
- (void) filterAllEventsIntoDictionary{
// start critical area
if (self.sortedKeys.count != 0) {
[self.sortedKeys removeAllObjects];
}
dispatch_async(self.filterMainQueue, ^{
[self internal_filterAllEventsIntoDictionary];
dispatch_sync(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
}
由于 internal_filterAllEventsIntoDictionary
方法也会访问 self.sortedKeys
,因此如果调用此代码两次,它会因开始时的 removeAllObjects
而崩溃。
我仍然需要在另一个线程中调用 internal...
方法,因为我不想阻塞 UI。那么,在 dispatch_async
调用尚未完成时阻止此方法开始的最佳方法是什么?
最佳答案
虽然我远不是并发专家,但在我看来,您需要锁定您的 sortedKeys
对象。但是,如果您使用传统的锁,您最终会阻塞主线程。
在 Grand Central Dispatch 世界中,推荐的锁替代方案是将代码的关键部分放在串行队列上。请参阅"Eliminating Lock-Based Code"在并发编程指南中。
如果您将 [self.sortedKeys removeAllObjects];
调用放入具有 internal...
调用的 block 所调度的同一队列上,则可以保证在该 block 完成之前它不会发生:
// start critical area
dispatch_async(self.filterMainQueue, ^{
if (self.sortedKeys.count != 0) {
[self.sortedKeys removeAllObjects];
}
});
这假设filterMainQueue
是串行。对临界区使用dispatch_async可以确保主线程不会被阻塞。另请注意 "Dispatch Queues and Thread Safety" 中的警告:
Do not call the
dispatch_sync
function from a task that is executing on the same queue that you pass to your function call. Doing so will deadlock the queue.
尽管只有当 internal...
方法执行某些操作导致再次调用该方法时,这才会成为问题。
关于objective-c - 保护关键代码不被再次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8163343/