使用dispatch_sync作为互斥锁

时间:2013-05-01 20:40:51

标签: ios objective-c multithreading grand-central-dispatch critical-section

这是我需要做的。 我希望dispatch_sync是使用GCD的最好方法

我有一段临界区代码放在Appdelegate的applicationDidBecomeActive回调中。

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

这是使用dispatch_sync进行此操作的正确方法吗?

2 个答案:

答案 0 :(得分:13)

dispatch_sync()在块完成之前不会返回,这意味着 在applicationDidBecomeActive完成之前,runCriticalSection不会返回 执行。

这可能不是您想要的,因此您必须使用dispatch_async()(已经如此) 在另一个答案中说明。

但是你不希望另一个runCriticalSection开始 如果前一个仍然在运行。这可以通过“计数信号量”来实现 (这也是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);
    });
}

答案 1 :(得分:0)

runCriticalSection方法将被多次调用,而不是同时调用,因此我不知道这是否是您想要实现的目标。

dispatch_sync只需将指定的块添加到串行队列(默认优先级全局队列),因此如果连续两次触发applicationDidBecomeActive,则队列将包含两个将运行的块{ {1}}。当第一个启动并完成执行时,第二个将启动,因此不会同时执行这两个块。

这是预期的行为吗?如果是这样,runCriticalSection是可行的方法。

作为附加组件:如果dispatch_sync执行繁重操作,请考虑runCriticalSection将阻止运行dispatch_sync方法的线程(如果您不调用,则为{1}}方法从另一个线程手动完成该方法直到该操作完成。

如果你想避免这种情况,你应该这样做:

applicationDidBecomeActive
只要块被添加到队列中,

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等待块内的代码完成。