ios - 中止所有dispatch_semaphore_wait

标签 ios multithreading grand-central-dispatch semaphore

在 iOS 中,GCD 提供信号量来同步对有限资源的访问。

在我的程序中,我正在从外部设备读取数据。该外部设备可以断开连接,程序将永远不会再向信号量发出信号。所以我们最终会遇到以下情况:

  • 线程 1 正在等待信号量

    if (dispatch_semaphore_wait(self.writeSem, /* 15s timeout */)) {
    
  • 线程2知道不等待会成功

最终,dispatch_semaphore_wait 超时,返回 NO 并且线程 1 恢复运行。

我怎样才能立即使此 dispatch_semaphore_wait 失败,以便线程 1 立即得到 NO 并继续他的生命?我可以使用某种“取消信号量”吗?

最佳答案

如果没有额外的“机器”,信号量是错误的抽象。除了发出信号之外,没有“取消信号量等待”操作,并且当发出信号时,如果没有更多信息,您不知道它发出信号是因为成功还是终止。因此,您可以添加一个外部标志来指示信号是用于完成还是提前终止,但是您必须正确保护该标志以防止并发读取和写入。

这里使用的规范原语是一个条件变量,标准的 Cocoa 示例将使用 NSCondition。一个简单的示例可能如下所示:

NSCondition* cond = [NSCondition new];
__block BOOL workSucceeded = NO;
__block BOOL subordinateFinished = NO;
NSTimeInterval timeout = 5.0;

// Waiter
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [cond lock];
    while (!subordinateFinished)
    {
        if (![cond waitUntilDate: [NSDate dateWithTimeIntervalSinceNow: timeout]])
        {
            // Timed out...
            NSLog(@"Timed out waiting for work at: %@", [NSDate date]);
            break; // don't keep waiting
        }
        else if (workSucceeded)
        {
            // Signaled to indicate that work was done
            NSLog(@"Work finished at: %@", [NSDate date]);
        }
        else //if (!workSucceeded)
        {
            // Signaled to indicate premature termination.
            NSLog(@"Work prematurely terminated at: %@", [NSDate date]);
        }
    }
    [cond unlock];
});

// Actor
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"Work started at: %@", [NSDate date]);
    BOOL completed = NO;

    // Uncomment one of these to trigger each case
    // Finish on time:
    //sleep(1);
    //completed = YES;

    // Fail Early:
    //sleep(1);

    // Time out
    //sleep(timeout + 1);

    // ... and when done
    [cond lock];
    workSucceeded = completed;
    subordinateFinished = YES;
    [cond signal];
    [cond unlock];
});

这里需要理解的重要一点是,workSucceededsublinedFinished 受条件锁的保护,任何不持有锁的人都不会读取或写入。人们第一次使用 NSCondition 时常常不清楚的是,调用 -wait-waitUntilDate:-signal 的行为都会导致调用线程暂时放弃锁,并理解当该线程恢复执行时,它将再次持有锁。

希望这对您有所帮助。

关于ios - 中止所有dispatch_semaphore_wait,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29302381/

相关文章:

ios - 在 RubyMotion 中,如何在触摸后退链接时取消列表刷新?

ios - 将事件保存到用户的日历

iOS StoreKit 应用程序(应用程序内购买应用程序)- 互联网不可用时

ios - 在 iOS 的后台线程中绘图

java - 阻塞 BufferedReader 直到数据出现

ios - 在 Swift 中调用串行队列中的函数

ios - Swift - 加载搜索结果时的并发问题。我加载图像,发送请求,但请求为时已晚

ios - Xcode 中未显示 TestFlight 崩溃日志?

ios - MKMapView visibleMapRect 两次 - 不同的结果

c++ - 使用 Visual Studio Express 2013 为 C++ 代码创建独立的可执行文件