GCD - 阻塞队列上的dispatch_async

时间:2013-03-21 13:57:41

标签: objective-c grand-central-dispatch

如果dispatch_async队列中的代码块当前被其自己的dispatch_sync操作阻止,会发生什么?在dispatch_sync操作返回后,它们是锁定还是阻塞的队列会继续?

我创建了一个对象来管理对后备存储的访问(在本例中为SQLite)。它使用一个concurrent GCD队列,并且任何其他想要访问商店信息的对象都会将请求与一个将异步执行的块一起传递给管理器。发生的事情的本质是这(不是实际的代码):

- (void) executeRequest:(StoreRequest *)request withCompletionBlock:(void(^)(NSInteger result)block{
    dispatch_queue_t currentContext = dispatch_get_current_queue();
    dispatch_async(_storeQueue, ^{
        NSInteger result = [_store executeRequest:request];
        if (block){
            dispatch_async(currentContext, ^{
                block(result);
            }
        }
    });
}

实际代码有点复杂(我实际上排队并存储请求/块/上下文以在运行循环结束时执行)。我还使用dispatch_barrier_async来写请求以防止并发读/写。这一切都很好,但在某些情况下我还需要在商店上执行同步请求。现在,在任何排队操作之前不需要执行此请求,但我确实需要阻止请求队列,直到执行操作为止。这很容易做到:

- (NSInteger) executeRequest:(StoreRequest *)request{
    __block NSInteger result = 0;
    dispatch_sync(_storeQueue, ^{
        result = [_store executeRequest:request];
    });
    return result;
}

我的问题是:如果在同步操作之前放置的挂起异步操作在当前被同步调度阻塞的队列上异步调度代码块会发生什么。换句话说,上述操作将在_store队列结束时调度其请求并等待。但是很可能(甚至可能)前面的操作包括异步调度回到等待队列(用于其他操作)。这会锁定线程吗?由于排队的块是异步调度的,_store队列永远不会被阻塞,因此会完成,理论上允许它阻塞的队列继续...但我不确定异步调度的块会发生什么,或者如果将任何内容调度到块线程将其锁定。我会假设阻塞的队列将继续,完成它的请求,然后处理挂起的块,但我想确定。

实际上,既然我已经把这一切写完了,我很确定它会工作得很好,但无论如何我都会发布这个问题,以确保我没有遗漏任何东西。

2 个答案:

答案 0 :(得分:1)

dispatch_async永远不会阻止。就这么简单。

答案 1 :(得分:1)

dispatch_async本身永远不会阻止。它将块附加到队列的末尾并立即返回。

块会被执行吗?这取决于。在顺序队列中,如果一个块被阻塞,则在该块被解除阻塞并完成之前,不会执行任何其他块。在后台队列中,队列可以使用多个线程,因此即使某些块被阻止,它也只会启动其他块。如果被阻止的块的数量有限制,我还没有尝试过,但是很有可能所有未阻塞的块最终都会执行并完成,而你将被阻止。