0

メソッドにあるものの擬似コードは次のとおりです。

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 (上記を参照) から「ロックされていないときにロックが解除されました」という警告が表示されることです。

ここで、私が達成しようとしていることを説明しましょう。これはデータ フェッチャーの一部です。通常の場合、データが受信され、ブロック 1 が実行されます: 問題はありません。場合によっては、データのないブロック 2 が最初に誤って実行され、その直後にブロック 1 が実行されることがあります。これは私がNSCondition警告を受け取るときです。このまれなケースを見つけるために、私は2.0数秒待ちます。何が起こるかは次のとおりです。

  • Block2 は状態を通知します。
  • Lock-1 は失敗します。
  • predicateもうない0ので、待つ必要はありません。
  • 条件が再びアンロックされます。
  • 次にif、条件(predicate == 2)が true であるステートメントに進みます。
  • メソッドはすぐに Lock-2 を取得します。<<<< 根本原因
  • その後、メソッドは2.0数秒間待機します。
  • この 2 秒以内に block1 が実行され、状態が通知されます。
  • 次に、block1 が条件のロックを解除し、メソッドのロックも解除します。

根本的な原因 (上記を参照) は、ロックがメソッド (ワーカー/コンシューマー) によって取得されているのに、データ プロデューサーによってロックが取得されているはずです。私はこれを理解しようと多くの時間を費やしました。私が持っていた考えの 1 つは 2 つNSConditionの を使用することでしたが、物事がかなり絡み合っているため、これを理解できませんでした。

unlock注: ステートメントの内側に警告が表示されないのは奇妙ifです。

御時間ありがとうございます!

4

1 に答える 1