首页 文章

GCD - 阻塞队列上的dispatch_async

提问于
浏览
1

如果 dispatch_async 在's currently blocked by it'拥有 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 回答

  • 1

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

  • 1

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

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

相关问题