Objective c 信号量_wait()突然中止

Objective c 信号量_wait()突然中止,objective-c,xcode,multithreading,semaphore,Objective C,Xcode,Multithreading,Semaphore,我有一个应用程序,其线程创建为 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ }); 我挂起所有其他线程并继续执行此线程。 当这个线程在一个semaphore_wait()函数中旋转时,暂停应用程序或添加一些符号断点会立即导致它退出这个semaphore_wait(),尽管它不能退出。 我不知道原因。是否是XCode(4.5)导致了这种行为?如果您对如何在Cocoa中进行异步开

我有一个应用程序,其线程创建为

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

});
我挂起所有其他线程并继续执行此线程。 当这个线程在一个semaphore_wait()函数中旋转时,暂停应用程序或添加一些符号断点会立即导致它退出这个semaphore_wait(),尽管它不能退出。
我不知道原因。是否是XCode(4.5)导致了这种行为?

如果您对如何在Cocoa中进行异步开发有疑问,请参阅以下参考资料:

  • WWDC 2012视频
但是,简而言之,我们不使用
semaphore\u wait
(或同一类别中的其他函数)。我们绝对不会挂起线程或类似的东西

当我们绝对需要信号量在各种后台线程之间进行通信时,我们使用
dispatch\u semaphore\u create
dispatch\u semaphore\u wait
,以及
dispatch\u semaphore\u signal
(我从未见过那些表现出您描述的行为)。例如,我将创建一个信号量,在后台线程上等待它,并在60秒后发出信号,这不受调试器中快速暂停和恢复执行的影响:

// create a semaphore

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

// wait for signal on background thread (but don't block main thread)

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"Waiting ...");

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    NSLog(@"Waiting done.");
});

// after one minute signal the semaphore

double delayInSeconds = 60.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    NSLog(@"About to signal");

    dispatch_semaphore_signal(semaphore);

    NSLog(@"Signal sent");
});
这是一个相当不切实际的示例,信号量的使用也很差,但它说明了如何使用信号量

但是永远不要在主线程上执行任何阻塞操作,更不要说尝试挂起它。事实上,在iOS中,如果你在应用程序启动太长时间时阻止主线程,看门狗可能会杀死你的应用程序

当您浏览标准视频和时,您将看到,调度队列和操作队列的标准用法通常完全不需要信号量(尽管我们偶尔会使用它们)

所以,如果你的问题真的是关于信号量的,也许其他人可以帮助你。但是,如果您对适当的Cocoa异步模式有疑问,请告诉我们您在功能上试图实现什么,我们可以为您指出正确的方向


Cocoa开发人员可以使用几种技术(调度队列、操作队列、线程等),每种技术都有自己的优点,非常适合于某个场景。但是,我们很少再需要求助于直接线程编程,也不会使用
信号量\u wait
或尝试挂起线程。

似乎lldb在SIGSTOP消息方面存在问题。检查以下lldb版本

修订版155560

在发送SIGSTOP&resuming之前挂起程序线程,这样在等待SIGSTOP时其他线程就不会遇到问题

rdar://problem/11174834

当调试主线程上的信号量_wait()时会出现问题,后台线程上的信号量_wait()不受此lldb问题的影响

另外,dispatch\u semaphore\u wait()不受此问题的影响,因为它使用的dispatch\u semaphore\u wait\u slow()具有以下特性:

case DISPATCH_TIME_FOREVER:
    do {
        kr = semaphore_wait(dsema->dsema_port);
    } while (kr == KERN_ABORTED);


因此,当semaphore_wait()返回且KERN_被中止时,它将在等待时恢复。

您显示的代码不会创建线程。它只是将对块的引用放在队列上。在GCD内部,创建工作线程来为其队列提供服务。您不创建线程,也不拥有线程。现在还不清楚你说的挂起和恢复线程是什么意思。根据您的意思,您可能无权对GCD的线程执行此操作。因此,我不太了解cocoa队列,只是假设它们都是线程。我需要了解他们。总之,我测试了方法swizzling(method_setImplementation)并调用该方法(objc_msgSend)()时获得的锁(runtimeLock)。writer使用rwlock_write()创建一个信号量,等待读取器发出信号。当我挂起所有其他线程并在等待信号量时主线程旋转时,它无法得到信号。但当我暂停执行时,信号量_wait()返回并继续执行。它不知怎么发出了信号!?我以为它们都是独立的线程,但似乎不是。那么,我应该使用什么来在单独的线程上运行每个代码来测试这个场景呢?“cocoa的队列,只是假设它们都是线程。”一点也不。它们是建立在线程之上的非常强大的抽象,但是您不应该考虑线程本身。想想排队。你绝对不应该在GCD下进入和修改线程。在这种情况下,如果程序的行为异常,您不应该感到惊讶。除此之外,还可以看到@Rob提供的优秀链接。我尝试使用performSelectorInBackground:withObject:在分离的线程上运行它,但即使在这种情况下,在信号量_wait()中等待时暂停,它也会突然返回,尽管没有信号量。所以,我怀疑这是XCode lldb的一个特性还是一种bug。。。