我有一個遞歸函數,用於在併發隊列上調度新任務。我想限制同時計劃任務的數量,所以我使用一個信號量,以便每個任務都會等待,直到舊線程結束併發出信號燈信號。當所有正在運行的任務正在等待時,GCD死鎖不會啓動掛起的任務
但是我發現當達到最大運行線程數(64)並且它們都開始在信號量上等待時,隊列會死鎖。然後GCD不會開始新的任務,即使它的待處理隊列中有很多。
我在做什麼錯?這是我的代碼:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
dispatch_semaphore_t sem = dispatch_semaphore_create(10);
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
{
[self recurWithSemaphore:sem];
});
}
- (void)recurWithSemaphore:(dispatch_semaphore_t)sem
{
// do some lengthy work here...
// at this point we're done all but scheduling new tasks so let new tasks be created
dispatch_semaphore_signal(sem);
for (NSUInteger i = 0; i < 100; ++i)
{
// don't schedule new tasks until we have enough semaphore
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
{
[self recurWithSemaphore:sem];
});
}
}
我已經考慮過NSOperationQueue,但限制併發線程的數量與限制* scheduled *任務的數量不同。計劃任務即使在未運行時也會消耗大量內存,因此我想推遲計劃任務的時間。 – egd 2015-03-31 17:22:24
在我的代碼中,每個線程都會同時嘗試產生儘可能多的子任務,但由於與其他任務的爭用,它最終會在信號量上等待,因此沒有任何線程永遠不會退出。所以線程數量達到了最大GCD(約70),然後死鎖。從理論上講,當運行中的任務被阻塞時,GCD應該從掛起的隊列中啓動新的任務。我錯了嗎? – egd 2015-03-31 17:39:51
是的,我已經嘗試使用串行「調度程序」隊列以受管制的方式啓動新線程,但讓所有併發線程與單個調度程序隊列同步是一個巨大的性能瓶頸。所以我正在嘗試使用信號量進行同步。 – egd 2015-03-31 17:43:56