1

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

我创建了一个对象,用于管理对后备存储(在本例中为 SQLite)的访问。它使用一个concurrentGCD 队列,任何其他想要从存储中访问信息的对象都会向管理器传递一个请求以及一个异步执行的块。发生的事情的本质是这样的(不是实际的代码):

- (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队列永远不会被阻塞,因此将完成,理论上允许它阻塞的队列继续......但我不确定异步分派的块会发生什么,或者是否将任何内容分派给块线程会将其锁定。我会假设被阻塞的队列将继续,完成它的请求,然后处理待处理的块,但我想确定一下。

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

4

2 回答 2

1

dispatch_async从不阻塞。就是这么简单。

于 2013-03-21T14:52:23.357 回答
1

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

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

于 2014-06-23T12:14:30.903 回答