0

方法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 ...]

线程 1线程 2都将一个块(请求 1 请求 2)排入队列以从远程获取相同的数据。当请求 1完成时,它调用方法 2 来发出 _condition 信号:

我的问题是:

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

谢谢。

4

1 回答 1

0

如果您试图防止重复请求,您可以使用在启动请求时设置的布尔标志来执行此操作,然后在完成后清除。您将使用互斥锁/信号量/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 本身的引用,因此我可以取消它并在适当的情况下重新启动一个新的。

于 2015-10-18T17:38:33.600 回答