我有一个用:
创建的串行调度队列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文档支持。
答案 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;
}
因为每个方法的执行都可以在任何时候推迟,以支持另一个线程。