1

Is it possible to re-use a condition variable in a loop? I tried to create a thread pool and whenever a thread's turn comes main thread signals using the condition variable. In the beginning, the thread will wait for the signal and after this, it'll do its job and keeps looping until the loop ends. I tried this below

// one of the threads in the thread pool
while(a condition){
   pthread_cond_wait(&cond, &lock);       
   pthread_mutex_lock(&lock);
   // job
   pthread_mutex_unlock(&lock);
}

// in main thread, whenever a condition happens
// for a specific thread, main thread signals using condition variable
pthread_cond_signal(&cond);

What's wrong with this code?

Jenny
  • 41
  • 6
  • `pthread_cond_wait` accepts two arguments. –  Jun 07 '20 at 15:53
  • Thanks, I forgot to write in here. I added. – Jenny Jun 07 '20 at 15:54
  • The problem is not a syntax problem. There is a deadlock, when I execute it. – Jenny Jun 07 '20 at 15:55
  • I was asking exactly because this is important. You are locking the mutex after waiting. This doesn't make any sense. You need to re-read how condition variables work. –  Jun 07 '20 at 15:59
  • Aren't you supposed to lock the mutex before waiting on the condition variable? – Shawn Jun 07 '20 at 16:00
  • wait and signal must be called while holding the mutex. – Jazzwave06 Jun 07 '20 at 16:02
  • I believe you have to do the lock before, and do the wait in a loop checking for completion. Then, do stuff, then unlock. See: https://stackoverflow.com/questions/16522858/understanding-of-pthread-cond-wait-and-pthread-cond-signal – Craig Estey Jun 07 '20 at 16:06
  • The both cases cause a deadlock. I tried both but there was no difference. Is it the correct way to use this? If it is, maybe there is another problem that I should check in my code. – Jenny Jun 07 '20 at 16:08
  • If you call lock before wait (and lock before signal), and you still deadlock, then yes, there's another problem in the code. See [mcve]. – user3386109 Jun 07 '20 at 16:19
  • I think you should post your entire code. It should be downloadable, compile cleanly, and be runnable. – Craig Estey Jun 07 '20 at 16:21
  • @Jenny The usage you show is _incorrect_. Function `wait` locks the mutex before returning. You are locking locked mutex. –  Jun 07 '20 at 16:35
  • @StaceyGirl You're correct, the order is incorrect [and should be fixed], but the effect is a bit more subtle. pthread mutexes are recursive and have an ownership refcount. `pthread_mutex_lock` will check to see if the current thread already owns the mutex and, if so, will just increment the refcount. So, in the waiting thread, if it comes out of `pthread_cond_wait`, the `pthread_mutex_lock` _after_ it _won't_ block, but the refcount will be higher that it should be. So, the waiting thread will never properly release the lock and the _signaling_ thread will block. – Craig Estey Jun 07 '20 at 18:05
  • @CraigEstey "Normal" pthread mutex is non-recursive and locking it twice is undefined. To get recursive behavior you have to set mutex type to `PTHREAD_MUTEX_RECURSIVE` when creating it. In theory implementation can choose to make it recursive, but I don't know of such implementations. –  Jun 07 '20 at 18:12
  • @StaceyGirl `glibc` [at least] defaults to recursive. Try this: `#include #include pthread_mutex_t mutex; int main(void) { pthread_mutex_init(&mutex,NULL); printf("main: LOCK1\n"); pthread_mutex_lock(&mutex); printf("main: LOCK2\n"); pthread_mutex_lock(&mutex); printf("main: DONE\n"); return 0; }` – Craig Estey Jun 07 '20 at 18:20
  • @CraigEstey Sorry, but this hangs with glibc 2.31 –  Jun 07 '20 at 18:22
  • @StaceyGirl Oops. I had pretested this before my first comment but left off the `-lpthread`. Hangs here now too [And, I had looked in `nptl/pthread_mutex_lock.c`] It built because of what `nptl/forward.c` does. – Craig Estey Jun 07 '20 at 18:36

1 Answers1

1

Thank you all for answering this question. I gathered both your answers and the sources I found online and found a solution for my own question. The order should be like this:

// thread1
pthread_mutex_lock(&lock);
pthread_cond_wait(&cond, &lock);
// job
pthread_mutex_unlock(&lock);

// main thread
pthread_mutex_lock(&lock);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
Jenny
  • 41
  • 6