我正在開發一個使用GCD運行大量後臺作業的MacOS X應用程序。後臺作業使用CLucene來索引文檔,並在子上下文中訪問核心數據。使用dispatch_semaphore_t併發隊列中的死鎖
這些作業都是在短時間內產生的(在DISPATCH_QUEUE_CONCURRENT創建的隊列上使用dispatch_async),但只有4個同時執行實際工作。這是通過使用dispatch_semaphore_t完成的,通過在作業開始時等待並在作業完成時釋放它。
我看到,當一個很奇怪的,可靠的可重複的僵局:
- 後臺作業仍在運行
- 用戶焦點切換到另一個應用程序,然後回
NSWindow被顯然嘗試在顯示菜單欄時發送通知時出現死鎖。這是主線程的堆棧跟蹤,當發生這種情況:
#0 0x00007fff870ae6c2 in semaphore_wait_trap()
#1 0x00007fff8b1bf486 in _dispatch_semaphore_wait_slow()
#2 0x00007fff8b69c12b in -[_NSDNXPCConnection sendMessage:waitForAck:]()
#3 0x00007fff8b57ced5 in _CFXNotificationPost()
#4 0x00007fff8b58bbf3 in CFNotificationCenterPostNotification()
#5 0x00007fff902ae174 in HIS_XPC_CFNotificationCenterPostNotification()
#6 0x00007fff8bd3612a in BroadcastToolboxMessage()
#7 0x00007fff8bd6d063 in MenuBarInstance::Show(MenuBarAnimationStyle, unsigned char, unsigned char, unsigned char)()
#8 0x00007fff8bd98144 in SetMenuBarObscured()
#9 0x00007fff8bd97e0f in HIApplication::HandleActivated(OpaqueEventRef*, unsigned char, OpaqueWindowPtr*)()
#10 0x00007fff8bd95407 in HIApplication::EventObserver(unsigned int, OpaqueEventRef*, void*)()
#11 0x00007fff8bd636e0 in _NotifyEventLoopObservers()
#12 0x00007fff898dc018 in -[NSWindow sendEvent:]()
#13 0x00007fff898d8744 in -[NSApplication sendEvent:]()
#14 0x00007fff897ee2fa in -[NSApplication run]()
#15 0x00007fff89792cb6 in NSApplicationMain()
#16 0x0000000100001e52 in main at /Users/mspong/dev/Indx/Indx/Indx/main.m:13
#17 0x00007fff86b7b7e1 in start()
所有正在運行的後臺作業完成他們的工作,但沒有進一步的工作可以訪問上述信號。每個線程都卡在semaphore_wait_trap上。
我無法想象我可能會做什麼(顯然)導致無關的信號量(包括我的和蘋果的)卡住。任何人都可以提供一些關於如何進一步調查的建議嗎?
嗯 - 如果'[_NSDNXPCConnection sendMessage:waitForAck:]'試圖使用併發隊列,肯定會出現這種情況。 我沒有意識到併發隊列中的阻塞是不好的設計,在某些情況下我肯定排隊超過64個作業。我會重新思考我是如何處理這些工作的。 – Xtapolapocetl
看起來確實是這個問題。我改寫它來使用一個任務有限的NSOperationQueue,而現在一切似乎都很好。謝謝! – Xtapolapocetl
@Catfish_Man,我有類似的問題。感謝關於GCD併發隊列線程限制的提示 - 請你詳細說明我可以在哪裏閱讀它(有沒有官方文檔)? –