Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 在并发队列中使用dispatch\u信号量\u t的死锁_Objective C_Multithreading_Macos_Cocoa_Grand Central Dispatch - Fatal编程技术网

Objective c 在并发队列中使用dispatch\u信号量\u t的死锁

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

我正在开发一个MacOS X应用程序,它使用GCD运行大量后台作业。后台作业使用CLucene索引文档,并在子上下文上访问核心数据

这些作业都是在短时间内生成的(在使用dispatch\u queue\u CONCURRENT创建的队列上使用dispatch\u async),但只有4个作业同时执行实际工作。这是通过使用dispatch_信号量来完成的,在作业开始时等待它,在作业完成时释放它

我看到了一个非常奇怪的、可靠重现的死锁:

  • 后台作业仍在运行
  • 用户将焦点切换到另一个应用程序,然后返回
  • 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 ()
    
    
    所有正在运行的后台作业都会完成它们的工作,但没有其他作业可以访问上述信号量。每个线程都卡在信号灯等待陷阱上


    我无法想象我可能会做什么(显然)导致无关的信号量(我的和苹果的)卡住。有人能就如何进一步调查这个问题提供一些建议吗?

    有没有可能您达到了GCD并发队列线程限制(64个线程),然后做了一些尝试在并发队列上工作的事情?这将导致整个框架出现随机死锁


    如果是这样的话,我唯一的建议是:永远不要在并发队列中阻塞。

    Hmm-如果
    [\u NSDNXPCConnection sendMessage:waitForAck:][/code>试图使用并发队列,那么肯定会是这样。我没有意识到在并发队列中阻塞是一种糟糕的设计,在某些情况下,我肯定会让超过64个作业排队。我会重新考虑如何处理这些工作。看起来这确实是个问题。我重写了它,改为使用任务受限的NSOperationQueue,现在一切似乎都好了。谢谢@鲶鱼先生,我也有类似的问题。感谢关于GCD并发队列线程限制的提示-您能告诉我在哪里可以详细阅读它(有官方文档吗)?我不确定它在哪里被记录,但它的逻辑相当简单:如果队列上的工作不受cpu限制,它必须在某个方面被阻止。如果它在某个地方被阻止,并且有额外的GCD作业等待线程,那么它被阻止的地方可能就是其中之一,因此它必须生成一个线程。如果GCD无限期地产生线程,进程将达到OS线程限制并崩溃,因此必须有一个上限。串行GCD队列不受相同上限的约束,因为它们不会产生>1个线程,所以在串行队列中阻塞通常是可以的。坚持CPU工作或并发工作中的低工作计数。理想情况下,如果可以避免的话,不要阻塞!例如,如果您使用dispatch_io进行读取和写入,它将在等待时使用零线程,从而完全避免此问题。