9

我创建了一个串行调度队列:

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: 方法,它们是否保证以相同的顺序执行,或者 isObjectInQueue 会/可以先执行吗?

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

我见过类似的问题,答案是双向的,所以我正在寻找一个明确的答案,最好有 Apple 文档支持。

4

2 回答 2

13

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

是的。

会/可以isObjectInQueue先执行吗?

是的。

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

基本上,这些块将按照它们被放入串行队列的顺序执行。这是 100% 保证的。但是,如果多个线程都在努力解决这个问题,那么一个线程可能会在另一个线程有机会添加之前先从队列中读取某些内容。

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

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

于 2013-01-12T12:49:26.983 回答
2

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

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

实际上,如果您按照queue.c 中 dispatch_async的源代码进行操作,您会看到该块在前台排队,只有在那之后,执行才会返回到调用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;
} 

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

于 2013-01-12T12:47:14.817 回答