且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

优雅的线程终止与pthread_cond_signal证明问题

更新时间:2022-10-15 14:32:11

Firstly, you have to change your predicate from

if ( msq.empty() ) {
  // no messages so wait for one.
  pthread_cond_wait( &cnd, &lock );
}

to

while ( msq.empty() ) {
  // no messages so wait for one.
  pthread_cond_wait( &cnd, &lock );
}

That's a pthreads thing, you have to guard yourself against spurious wakeups.

Now you can change that to

while ( msq.empty()  && !finished) {
  // no messages so wait for one.
  pthread_cond_wait( &cnd, &lock );
}

Since after that check, you already test whether finished is set and exits if so, all you have to do is signal all the threads.

So, in your teardown function, replace the loop with:

pthread_cond_broadcast(&cond);

That should ensure all threads wake up, and will see finished set to true and exit.

This is safe even if your threads are not stuck in pthread_cond_wait. If the threads are processing a message, they will not get the wakeup signal, however they will finish that processing, enter the loop again and see that finished == false and exit.

Another common pattern for this is to inject a poison message. A poison message is simply a special message your thread could recognise that would mean "STOP", you would place as many of those messages in your queue as you have threads.