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];
}

Thread 1が method1 にある場合、実行すること[_condition waitUtilDate ...];でロックが解除されます。 スレッド 2 はこの領域に入り、さらに を実行して条件を待ち[_condition waitUtilDate ...]ます。

スレッド 1スレッド 2の両方がブロック ( request 1 request 2 ) をキューに入れ、リモートから同じデータを取得しました。リクエスト 1が終了すると、メソッド 2 を呼び出して _condition を通知します。

私の質問は次のとおりです。

  • Thread 1Thread 2のどちらが通知されますか?
  • リクエスト 1リクエスト 2は同じことを行っているため、両方のスレッド ( ) にシグナルを送って、リクエスト 1が終了したときにリクエスト2broadcastをキャンセルできます。ただし、より良い方法は、リクエスト 1が送信された後、スレッド 2がクリティカル エリアに入るの を拒否することです。しかし、クリティカルエリアに入る前に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 に答える