Reputation: 4774
I implemented a simple ThreadPool that uses std::list<Tasks> mTasks
for task list.
All the threads waits on a conditional variable using the following code :
EnterCriticalSection(&mCriticalSection);
while(mTasks.size() ==0)
SleepConditionVariableCS(&mConditionVariable,&mCriticalSection, INFINITE);
Until someone adds something to the list and then one of them is waken up.
I used a while that checks that the task list is not empty although the only way to be waken up is by adding a new task to the list(so it can't be empty), the reason i did this is because in the MSDN it's written :
Condition variables are subject to spurious wakeups (those not associated with an explicit wake) and stolen wakeups (another thread manages to run before the woken thread). Therefore, you should recheck a predicate (typically in a while loop) after a sleep operation returns.
But what are those spurious wakeups, what will wake up my variable ?
Upvotes: 4
Views: 1197
Reputation: 62542
I believe that the problem is down to synchronization between multiple processors in a multi-processor system.
In order to keep conditional variables as lightweight as possible implementations use certain threading primitives that, whilst thread safe, will cause the conditonal variable to register two notify()
style calls when only one has actually been made. This is a rare scenario, and rather that making less efficient by handling this scenario the designers push the issue into user code where you only have to worry about it if it might affect you.
Upvotes: 1
Reputation: 19855
My understanding on this topic, at the time I studied it at the university, was that to implement 100% safe condition variables would have been too expensive from a performance perspective.
The wikipedia page about spurious wakeups has a quote from David R. Butenhof (the author of Programming with POSIX Threads
) saying:
This means that when you wait on a condition variable, the wait may (occasionally) return when no thread specifically broadcast or signaled that condition variable. Spurious wakeups may sound strange, but on some multiprocessor systems, making condition wakeup completely predictable might substantially slow all condition variable operations. The race conditions that cause spurious wakeups should be considered rare
Checking a condition in a while
loop is a good practice that will certainly avoid this problem.
For what concerns having more details on why this actually can happen, I am sorry, but I cannot provide such insights.
Upvotes: 2