保护关键代码免于再次被调用 [英] Protecting critical code from being called again

查看:68
本文介绍了保护关键代码免于再次被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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];
        });
    });
}

由于internal_filterAllEventsIntoDictionary方法也访问self.sortedKeys,因此如果两次调用此代码,则由于开头的removeAllObjects而崩溃.

Since the internal_filterAllEventsIntoDictionary method also accesses self.sortedKeys, if this code is called twice, it crashes because of removeAllObjects at the start.

我仍然需要在另一个线程中调用internal...方法,因为我不想阻塞UI.那么,在dispatch_async调用仍未完成的情况下阻止此方法启动的最佳方法是什么?

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?

推荐答案

虽然我不是一名并发专家,但听起来像我需要锁定sortedKeys对象.但是,如果使用传统锁,最终将阻塞主线程.

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.

在Grand Central Dispatch的世界中,建议替换的锁是将关键代码段放在串行队列中.参见消除基于锁定的代码" .

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.

如果将[self.sortedKeys removeAllObjects];调用放在安排了internal...调用的块所在的队列中,则可以确保在该块完成之前不会发生:

If you put the [self.sortedKeys removeAllObjects]; call onto the same queue that the block with the internal... call is scheduled on, you guarantee that it won't happen until after that block completes:

// start critical area
dispatch_async(self.filterMainQueue, ^{
    if (self.sortedKeys.count != 0) {
        [self.sortedKeys removeAllObjects];
    }
});

这假定filterMainQueue serial .在关键部分使用dispatch_async可确保不会阻塞主线程.另请注意:

This assumes that filterMainQueue is serial. Using dispatch_async for the critical section ensures that the main thread will not be blocked. Also note the warning in "Dispatch Queues and Thread Safety":

请勿在传递给函数调用的同一队列中正在执行的任务中调用dispatch_sync函数.这样做会死锁队列.

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...方法所做的事情导致该方法再次被调用时,这才是一个问题.

Although this will only be an issue if the internal... method does something that causes this method to be called again.

这篇关于保护关键代码免于再次被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆