2

次のように動作するタイマーを作成しました。タイマーを使用するクラスは、コールバック関数を実装しますcall_()。タイマーは別のスレッドで実行さcall_()れ、タイマーが期限切れになると実行されます。

私のテストプログラムは次のとおりです。

void TestCase::loop()
{
  unique_lock<mutex> lock(*this);

  while(running_)
  {
     timer_->SetTimer(time);
     signal_.wait(lock);
     do_something();
  }
}

void TestCase::call_()
{
  signal_.notify_all();
}

timeが非常に小さい場合(たとえば 2 ミリ秒)、テスト プログラムが実行される場合と実行do_something()されない場合があります (テスト プログラムの異なる実行で)。

私の推測では競合状態timeです。call()_signal_.notify_all()signal_.wait(lock)

this_thread::sleep(posix_time::milliseconds(2))beforesignal_.notify_all()を 追加するdo_something()と、ほぼすべての実行で実行され、sleep(5)すべて正常に動作します。

signal_.wait(lock)が前に実行されることをどのように保証できsignal_.notify_all()ますか?

4

1 に答える 1

1

signal_waitタイムアウト値が非常に小さい場合、タイマー スレッドがステートメントを実行する前にメイン スレッドがステートメントに到達することを保証する方法はありませんsignal_.notify_all

ワンショット タイマーを使用しているため、条件変数の代わりにセマフォを使用して 2 つのスレッドを同期することをお勧めします。

条件変数で見たように、メカニズムが正しく機能するためには、待機と通知を実行する順序があります。

セマフォを使用すると、待機を実行しているスレッドも、別のスレッドがセマフォをポストするまで停止しますが、待機およびポスト操作に到達する順序は必要ありません。ポストに最初に到達した場合、待機はすぐに返されます (そして成功します)。

于 2012-11-29T13:52:24.870 に答える