【问题标题】:How to use NSCondition when there are two different places that signal & wait当有两个不同的地方发出信号并等待时如何使用条件
【发布时间】:2014-03-31 13:10:17
【问题描述】:

这是我在方法中的伪代码:

NSCondition condition = [[NSCondition alloc] init];
int         predicate = 0;

dispatch_sync(dispatch_get_main_queue(), ^
{
    [condition lock];   // Lock-0
});

bindBlock1ForDataReceived(^()
{
    // Not main thread here.
    // Get on main thread, because lock and unlock must be run on same thread.
    dispatch_sync(dispatch_get_main_queue(), ^
    {
        predicate = 1;
        [condition signal];
        [condition unlock]; <<<<---- "unlocked when not locked"
    });
});

bindBlock2ForNoDataAvailable(^()
{
    // Not main thread here.
    // Get on main thread, because lock and unlock must be run on same thread.
    dispatch_sync(dispatch_get_main_queue(), ^
    {
        predicate = 2;
        [condition signal];
        [condition unlock];
    });
});

[condition lock];  // Lock-1
while (predicate == 0)
{
    [condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];
}
[condition unlock];

if (predicate == 2)
{
    [condition lock];  // Lock-2
    [condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
    [condition unlock];
}

问题是当第一个事件 2 和事件 1 发生时,我从 iOS(见上文)收到“未锁定时解锁”警告。

现在让我解释一下我要完成的工作:这是数据获取器的一部分。接收到正常情况数据并执行 block1:没有问题。有时,无数据块 2 会首先被虚假执行,紧接着是块 1;这是我收到NSCondition 警告的时候。为了捕捉这种罕见的情况,我等待2.0 秒。以下是发生的事情:

  • Block2 发出条件信号。
  • Lo​​ck-1 失效。
  • predicate 不再是 0,因此无需等待。
  • 条件再次解锁。
  • 然后我们继续if-语句,其条件(predicate == 2) 为真。
  • 该方法立即获得 Lock-2。
  • 随后该方法等待2.0 秒。
  • 在这 2 秒内 block1 被执行并发出条件信号。
  • 然后 block1 解锁条件,方法也解锁。

根本原因(见上文)是锁是由方法(工作者/消费者)获取的,而它应该是由数据生产者获取的。我花了很多时间试图弄清楚这一点。我的一个想法是使用两个NSConditions,但我无法弄清楚这一点,因为事情是相互交织的。

注意:我觉得奇怪的是,警告没有出现在 if 语句中的 unlock 中。

感谢您的宝贵时间!

【问题讨论】:

    标签: ios iphone multithreading mutex nscondition


    【解决方案1】:

    除了锁之外,最简单的方法是使用

    dispatch_group_t confirmGroup = dispatch_group_create(); // 1
    
    if (requestContacts) {
        dispatch_group_enter(confirmGroup); // 2
        [Extractor requestAccessAddressBook:^(BOOL isComplete) {
            if (isComplete) {
                dispatch_group_leave(confirmGroup); //2
            }
        }];
    
    
    }
    if (requestEvent) {
        dispatch_group_enter(confirmGroup); // 3       
        [Extractor requestAccessEvents:^(BOOL isComplete) {
            if (isComplete) {
                dispatch_group_leave(confirmGroup); // 3
            }
        }];
    }
    if (requestPhoto) {
        dispatch_group_enter(confirmGroup); // 4
        [Extractor requestAccessPhotos:^(BOOL isComplete) {
            if (isComplete) {
                dispatch_group_leave(confirmGroup); //4
            }
        }];
    }
    NSLog(@"dispatch_group_wait confirmations");
    dispatch_group_wait(confirmGroup, DISPATCH_TIME_FOREVER); // 5
    

    【讨论】:

    • 确实很干净
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多