objective-c - 保护关键代码不被再次调用

标签 objective-c cocoa locking blocking grand-central-dispatch

我需要保护代码的关键区域,该区域是多线程的。我想防止在另一个线程完成之前多次调用它。这就是我正在处理的内容:

- (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/

相关文章:

ios - 前向声明和参数化类

ios - UITableViewCell 内的 UITextfield 文本在滚动时消失

Java for循环线程锁

c - 在没有锁的情况下将循环缓冲区与写入和读取操作同步

java - 同步方法中的重入

objective-c - 如何使所有 Core Data 对象继承 self 的类而不是 NSManagedObject?

css - 如何理解这个崩溃报告? SIGSEGV

cocoa - 如何将 HTML 元素添加到 Cocoa Webview

cocoa - stringByEvaluatingJavaScriptFromString 不起作用

更新后 Xcode 找不到模块