dispatch_async vs dispatch_sync执行顺序

时间:2013-01-12 11:47:19

标签: objective-c concurrency sync grand-central-dispatch dispatch-async

我有一个用:

创建的串行调度队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.unique.name.queue", DISPATCH_QUEUE_SERIAL);

我想使用这个串行队列来确保类访问的线程安全,同时自动异步工作,不需要返回调用线程。

- (void)addObjectToQueue:(id)object
{
    dispatch_async(serialQueue, ^{
        // process object and add to queue
    }); 
}

- (BOOL)isObjectInQueue:(id)object
{
    __block BOOL returnValue = NO;
    dispatch_sync(serialQueue, ^{
        // work out return value
    });
    return returnValue;
} 

如果我调用addObjectToQueue:方法,然后立即调用isObjectInQueue:方法,它们是否保证以相同的顺序执行,或者is / In可以先执行isObjectInQueue?

换句话说,dispatch_async的执行与dispatch_sync(立即调度块)完全相同,只是它不会阻塞调用线程吗?

我已经看到类似的问题,答案是双向的,所以我正在寻找一个明确的答案,最好用Apple文档支持。

2 个答案:

答案 0 :(得分:13)

  

它们是否保证以相同的顺序执行?

  

isObjectInQueue会先/先执行吗?

两个答案都是肯定的原因是你应该考虑线程化。这可能是您首先使用串行队列的原因。您正在访问该队列线程安全。

基本上,这些块将按照它们放在串行队列中的顺序执行。这是100%保证。但是,如果多个线程正在捣乱,那么在另一个线程有机会添加它之前,一个线程可能首先从队列中读取内容。

  

换句话说,dispatch_async的执行与dispatch_sync完全相同(立即调度块),除了它不会阻塞调用线程吗?

没错。在这两种情况下,块都会添加到队列中。它会立即添加。 dispatch_sync只是在返回之前等待块完成,而dispatch_async立即返回。

答案 1 :(得分:2)

我想您的问题是,当dispatch_async仍在执行队列操作时,主线程是否会继续运行?我认为它不会,因为这值得明确提及。如果有的话,我在dispatch_async.3中发现了这一点,这表明情况就是这样:

  

从概念上讲,dispatch_sync()是一个方便的包装器   dispatch_async()添加了一个等待的信号量   块的完成,以及块周围的包装器发出信号   完成。

事实上,如果您遵循dispatch_async in queue.c的源代码,您将看到该块在前台排队,并且只有在此之后,执行才会返回到调用dispatch_async的代码。因此,如果队列是串行的,则dispatch_async后跟来自同一线程的dispatch_sync 将按顺序排列块。

因为dispatch_sync将阻塞直到块(以及串行队列中的所有块)完成执行,因此您的代码将是正确的。 isObjectInQueue:将正确报告之前添加的对象是否在队列中。

编辑:在多线程环境中,我会将上面的代码编写为:

- (void)addObjectToQueue:(id)object
{
    dispatch_barrier_async(_queue, ^{
        // process object and add to queue
    });
}

- (BOOL)isObjectInQueue:(id)object
{
    __block BOOL returnValue = NO;
    dispatch_sync(_queue, ^{
        // work out return value
    });
    return returnValue;
} 

因为每个方法的执行都可以在任何时候推迟,以支持另一个线程。