简体   繁体   English

使用dispatch_sync作为互斥锁

[英]using dispatch_sync as a mutex lock

Here is what I need to do. 这是我需要做的。 I hope dispatch_sync would be the best way to do it using GCD 我希望dispatch_sync是使用GCD完成它的最佳方式

I have a certain piece of critical section code that is placed in the applicationDidBecomeActive callback in Appdelegate.. 我有一段临界区代码放在Appdelegate的applicationDidBecomeActive回调中。

I am wrapping up that method inside a dispatch_sync call so that it gets called only once no matter how many times applicationDidBecomeActive is called 我在dispatch_sync调用中包装该方法,因此无论调用applicationDidBecomeActive多少次,它都只被调用一次

- (void)applicationDidBecomeActive:(UIApplication *)application{    
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    
    NSLog(@"Thread created");
    //crtical code
    [self runCriticalSection];        
});}

Is this the right way for doing it using dispatch_sync? 这是使用dispatch_sync执行此操作的正确方法吗?

dispatch_sync() does not return until the block has finished, which means that applicationDidBecomeActive does not return until runCriticalSection has finished execution. 在块完成之前, dispatch_sync()不会返回,这意味着在runCriticalSection完成执行之前, applicationDidBecomeActive不会返回。

This is probably not what you want, therefore you have to use dispatch_async() (as already stated in the other answer). 这可能不是你想要的,因此你必须使用dispatch_async() (如另一个答案中所述)。

But you don't want another runCriticalSection to start if the previous one is still running. 但是如果上一个runCriticalSection仍在运行,你不希望另一个runCriticalSection启动。 This can be achieved with a "counting semaphore" (which are also a feature of GCD): 这可以通过“计数信号量”(这也是GCD的一个特征)来实现:

static dispatch_semaphore_t sema; // The semaphore
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // Initialize with count=1 (this is executed only once):
    sema = dispatch_semaphore_create(1);
});

// Try to decrement the semaphore. This succeeds if the count is still 1
// (meaning that runCriticalSection is not executing), and fails if the 
// current count is 0 (meaning that runCriticalSection is executing):
if (dispatch_semaphore_wait(sema, DISPATCH_TIME_NOW) == 0) {
    // Success, semaphore count is now 0.
    // Start asynchronous operation.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //critical code
        [self runCriticalSection];
        // Increment the semaphore count (from 0 to 1), so that the next call
        // to applicationDidBecomeActive will start a new operation:
        dispatch_semaphore_signal(sema);
    });
}

The runCriticalSection method will be called multiple times, just not concurrently, so I don't know if this is what you want to achieve. runCriticalSection方法将被多次调用,而不是同时调用,因此我不知道这是否是您想要实现的。

dispatch_sync just add the specified block to a serial queue (the default priority global queue), so if applicationDidBecomeActive gets fired two times in a row, the queue will contain two blocks that will run runCriticalSection . dispatch_sync只是将指定的块添加到串行队列(默认优先级全局队列),因此如果applicationDidBecomeActive连续触发两次,则队列将包含两个将运行runCriticalSection块。 As the first one starts and finishes its execution, the second one will start, so there will not be any execution of the two blocks at the same time. 当第一个启动并完成其执行时,第二个将启动,因此不会同时执行这两个块。

Is this the expected behavior? 这是预期的行为吗? If so, dispatch_sync is the way to go. 如果是这样, dispatch_sync是要走的路。

As an add-on: if runCriticalSection performs an heavy operation, consider that dispatch_sync will block the thread that runs the applicationDidBecomeActive method (the main one if you don't call the method by hand from another thread) until that operation is finished. 作为附加组件:如果runCriticalSection执行繁重的操作,请考虑dispatch_sync将阻止运行applicationDidBecomeActive方法的线程(如果您不从另一个线程手动调用该方法,则为主要方法),直到该操作完成。

If you want to avoid this, you should do something like: 如果你想避免这种情况,你应该做的事情如下:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    
    [self runCriticalSectionOnComplete:^{
       // If you want to perform something on completion, place it here. This is called asynchronously, without blocking the main thread.
    }];        
});

dispatch_async will return as soon as the block is added to the queue, while dispatch_sync waits for the code inside the block to be completed. 一旦将块添加到队列, dispatch_async将立即返回,而dispatch_sync等待块内的代码完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM