【问题标题】:NSCondtion with multiple threads具有多个线程的 NSCondtion
【发布时间】:2015-10-18 12:47:01
【问题描述】:

方法1:

 - (void) method1
 {
    [_condition lock];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
         //Fetach data from remote, when finished call method2
         [self fetchData]; 
    });

    [_condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:30.0]];

    // Do something.
    [_condition unlock];
}

方法2:

- (void) method2
 {
    [_condition lock];
    [_condition signal];
    [_condition unlock];
}

如果 线程 1 在方法 1 中,通过执行 [_condition waitUtilDate ...]; 来解锁它的锁。 线程 2 进入该区域并通过执行[_condition waitUtilDate ...] 来等待条件。

Thread 1Thread 2 都将 Block(request 1 request 2) 排入队列以获取相同的来自远程的数据。当 request 1 完成时,它会调用 method2 来发出_condition:

我的问题是:

  • 线程 1 还是 线程 2 将发出信号?
  • 因为 request 1request 2 正在做同样的事情,我可以向两个线程发出信号(broadcast)并取消 request 2 请求 1 完成时。但是,更好的方法是在request 1发出后,拒绝Thread 2进入临界区。但是在进入关键区域之前我无法锁定两次。那么我能做什么呢?

谢谢。

【问题讨论】:

    标签: objective-c locking signals nscondition ios-multithreading


    【解决方案1】:

    如果您想防止重复请求,您可以使用在启动请求时设置的布尔标志来执行此操作,然后在完成后清除。您可以使用互斥锁/信号量/NSLock/等来保护您的关键区域。

    [_lock lock];
    if (_fetching) {
       [_lock unlock];
       return;
    }
    
    _fetching = YES;
    
    [self startRequestWithCompletion: ^{ 
       [_lock lock];
       _fetching = NO;
       [_lock unlock]; 
    }];
    
    [_lock unlock];
    

    或者您可以使用 NSOperationQueue 和 NSOperation 更优雅地处理这个问题。在开始新的队列之前,您需要测试队列以查看是否有任何挂起或正在运行的操作。

    if (_operationQueue.operationCount)
        return;
    
    [_operationQueue addOperationWithBlock: ^{
        // get your data
    }];
    

    您如何执行此操作实际上取决于您要获取的确切内容以及响应是否可能会根据输入数据而改变。例如,我广泛使用 NSOperations 来管理后台计算。但是,用户输入可能会改变这些计算的结果并使之前的任何工作无效。我保留了 NSOperation 本身的引用,因此我可以取消它并在适当的时候重新启动一个新的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 1970-01-01
      • 2013-03-02
      • 1970-01-01
      相关资源
      最近更新 更多