2013-03-21 89 views
1

会发生什么,如果你dispatch_async的代码上,因此目前阻止它自己dispatch_sync操作的队列中的块?在dispatch_sync操作返回后,它们是否会锁定或阻止队列继续?GCD - dispatch_async上阻塞队列

我有我创建的管理访问后备存储器(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队列将永远不会被阻塞,因此将完成,理论上允许它的阻止继续排队......但我不知道与被异步分派块会发生什么,或者调度什么一个块线程将其锁定。我会假设被阻止的队列将继续,完成请求,然后处理待处理的块,但我想确保。

其实,现在我已经写了这一切,我敢肯定它会工作得很好,但我还是要去张贴这个问题,以确保我不会遗漏任何东西。

回答

1

dispatch_async不会阻塞。就这么简单。

+0

是的,我并不担心'_store'队列,因为它的所有调度都是异步的。我很担心它发送的队列,因为队列在发送过程中被阻塞。大部分时候,我只是把事情弄糊涂了,开始把队列想成线程。我有时会忘记队列不是线程,所以当然被调度的块将等到被阻塞的队列返回并继续正常。这是GCD的重点......也许更多的咖啡会有所帮助。 :) – 2013-03-21 15:25:19

1

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

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

+0

GCD有64个线程限制。请参阅http://stackoverflow.com/questions/15150308/workaround-on-the-threads-limit-in-grand-central-dispatch – 2014-07-10 10:00:27