メソッドにあるものの擬似コードは次のとおりです。
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
です。
御時間ありがとうございます!