Objective c 在并发队列中使用dispatch\u信号量\u t的死锁
我正在开发一个MacOS X应用程序,它使用GCD运行大量后台作业。后台作业使用CLucene索引文档,并在子上下文上访问核心数据 这些作业都是在短时间内生成的(在使用dispatch\u queue\u CONCURRENT创建的队列上使用dispatch\u async),但只有4个作业同时执行实际工作。这是通过使用dispatch_信号量来完成的,在作业开始时等待它,在作业完成时释放它 我看到了一个非常奇怪的、可靠重现的死锁:Objective c 在并发队列中使用dispatch\u信号量\u t的死锁,objective-c,multithreading,macos,cocoa,grand-central-dispatch,Objective C,Multithreading,Macos,Cocoa,Grand Central Dispatch,我正在开发一个MacOS X应用程序,它使用GCD运行大量后台作业。后台作业使用CLucene索引文档,并在子上下文上访问核心数据 这些作业都是在短时间内生成的(在使用dispatch\u queue\u CONCURRENT创建的队列上使用dispatch\u async),但只有4个作业同时执行实际工作。这是通过使用dispatch_信号量来完成的,在作业开始时等待它,在作业完成时释放它 我看到了一个非常奇怪的、可靠重现的死锁: 后台作业仍在运行 用户将焦点切换到另一个应用程序,然后返回 N
#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 ()
所有正在运行的后台作业都会完成它们的工作,但没有其他作业可以访问上述信号量。每个线程都卡在信号灯等待陷阱上
我无法想象我可能会做什么(显然)导致无关的信号量(我的和苹果的)卡住。有人能就如何进一步调查这个问题提供一些建议吗?有没有可能您达到了GCD并发队列线程限制(64个线程),然后做了一些尝试在并发队列上工作的事情?这将导致整个框架出现随机死锁
如果是这样的话,我唯一的建议是:永远不要在并发队列中阻塞。Hmm-如果
[\u NSDNXPCConnection sendMessage:waitForAck:][/code>试图使用并发队列,那么肯定会是这样。我没有意识到在并发队列中阻塞是一种糟糕的设计,在某些情况下,我肯定会让超过64个作业排队。我会重新考虑如何处理这些工作。看起来这确实是个问题。我重写了它,改为使用任务受限的NSOperationQueue,现在一切似乎都好了。谢谢@鲶鱼先生,我也有类似的问题。感谢关于GCD并发队列线程限制的提示-您能告诉我在哪里可以详细阅读它(有官方文档吗)?我不确定它在哪里被记录,但它的逻辑相当简单:如果队列上的工作不受cpu限制,它必须在某个方面被阻止。如果它在某个地方被阻止,并且有额外的GCD作业等待线程,那么它被阻止的地方可能就是其中之一,因此它必须生成一个线程。如果GCD无限期地产生线程,进程将达到OS线程限制并崩溃,因此必须有一个上限。串行GCD队列不受相同上限的约束,因为它们不会产生>1个线程,所以在串行队列中阻塞通常是可以的。坚持CPU工作或并发工作中的低工作计数。理想情况下,如果可以避免的话,不要阻塞!例如,如果您使用dispatch_io进行读取和写入,它将在等待时使用零线程,从而完全避免此问题。