保护关键代码不被再次调用
我需要保护代码的关键区域,该区域是多线程的。我想防止在另一个线程完成之前多次调用它。这就是我正在处理的内容:
- (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
调用尚未完成时阻止此方法开始的最佳方法是什么?
I need to protect a critical area of my code, which is multi-threaded. I want to prevent it from being called multiple times before the other thread is finished. This is what I am working with:
- (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];
});
});
}
Since the internal_filterAllEventsIntoDictionary
method also accesses self.sortedKeys
, if this code is called twice, it crashes because of removeAllObjects
at the start.
I still need to call the internal...
method in another thread since I don't want to block the UI. So what's the best way to block on the start of this method while the dispatch_async
call is still not finished?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然我远不是并发专家,但在我看来,您需要锁定您的
sortedKeys
对象。但是,如果您使用传统的锁,您最终会阻塞主线程。在 Grand Central Dispatch 的世界中,推荐的锁替代方案是将代码的关键部分放在串行队列上。请参阅 “消除基于锁的代码”。
如果您将
[self.sortedKeys removeAllObjects];
调用放入具有internal...
调用的块所安排的同一队列上,那么您保证它不会直到该块完成之后才会发生:这假设
filterMainQueue
是串行。对临界区使用dispatch_async可以确保主线程不会被阻塞。另请注意 "调度队列和线程安全":尽管只有当
internal...
方法执行某些操作导致再次调用该方法时,这才会成为问题。While I am far from being a concurrency expert, it sounds to me like you need a lock on your
sortedKeys
object. If you used a traditional lock, though, you'd end up blocking the main thread.The recommended replacement for locks in the world of Grand Central Dispatch is to put critical sections of code on a serial queue. See "Eliminating Lock-Based Code" in the Concurrency Programming Guide.
If you put the
[self.sortedKeys removeAllObjects];
call onto the same queue that the block with theinternal...
call is scheduled on, you guarantee that it won't happen until after that block completes:This assumes that
filterMainQueue
is serial. Usingdispatch_async
for the critical section ensures that the main thread will not be blocked. Also note the warning in "Dispatch Queues and Thread Safety":Although this will only be an issue if the
internal...
method does something that causes this method to be called again.