简体   繁体   中英

Prevent race condition

I wrote a timer which works in the following way: a class using the timer implements a callback function call_() . The timer runs in a separate thread and executes call_() when the timer expires.

My test program is as follows:

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

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

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

If time is very small (eg 2ms) the test program sometimes executes do_something() , sometimes not (in different runs of the test program).

My guess is a race condition, it seems that if time is small call()_ is executed (and thus signal_.notify_all() ) before signal_.wait(lock) .

If I add this_thread::sleep(posix_time::milliseconds(2)) before signal_.notify_all() , do_something() is executed in almost every run and for sleep(5) everything works fine.

How can I assure that signal_.wait(lock) is executed before signal_.notify_all() ?

With very small timeout values, there is no way to guarantee that the main thread reaches the signal_wait statement before the timer thread executes the signal_.notify_all statement.

As you are using a one-shot timer, a better alternative would be to use a semaphore instead of a condition variable to synchronize the two threads.

As you saw with condition variables, there is an order in which the wait and notify must be executed in order for the mechanism to work correctly.

With a semaphore, the thread executing the wait will also be stopped until another thread posts the semaphore, but there is no requirement in which order the wait and post operations are reached. If the post was reached first, the wait just returns immediately (and successful).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM