3
votes

A bit of confusion! What could be the problem if we look at the following scenario: My objective is to understand the mixture of condition variable with mutex.

T1

  1. LOCK { MUTEX }
  2. CHECK VARIABLE
  3. IF NOT SET, WAIT ON CONDITION VARIABLE
  4. UNLOCK {MUTEX} GO TO 1

T2

  1. MODIFY VARIABLE;
  2. SIGNAL CONDITION VARIABLE

There could be race condition between step 2. and 3., hence we use MUTEX. What I do not understand is the underlying idea of cond var + mutex.

3
what behavior do you want here? I could explain how this code is structured, but I don't see how it can be doing anything useful. Does T1 ever break out of that loop? Is is waiting for T2 to modify the variable?Erik
Shouldn't T2 lock the mutex before modifying the variable?sizzle
that would cause a deadlock because T1 keeps the lock while waiting for the condition variable to be signaledErik
@Erik, condition variables automatically unlock their linked mutex when you go into a wait.bdonlan
@bdonlan I don't think that the mutex refered to here is "linked" to the condition variable.Erik

3 Answers

1
votes

I'm taking some guesses about your context and the behavior you want, but I think that you want things to look like this:

T1:
1. lock mutex
2. check variable
3. unlock mutex
4. wait on condition variable
5. goto 1

T2:
1. lock mutex
2. modify variable
3. unlock mutex
4. signal condition variable

The mutex is to protect access to the variable so that you don't have different threads reading and writing to it all at the same time.

The condition variable is used to synchronize threads so that you can control the order in which things happen.

1
votes

There are two problems with omitting the lock on the write end:

  1. If your variable you're modifying cannot be written to atomically (ie, it's larger than an int - although the details depend on the CPU architecture you're using!), you need a lock to ensure you don't have "shearing". This is when a read occurs when the variable is partway written. For example, you could write 0xAAAAAAAABBBBBBBB to a 64-bit variable that was previously 0, and another thread might only see 0xAAAAAAAA00000000 or 0x00000000BBBBBBBB. The lock prevents readers from seeing the in-progress write, avoiding this problem.
  2. It's possible that the reader may see your variable in the still-need-to-wait state, then before it can go to sleep, the writer could update the variable and signal the condition variable. As a result, your thread goes to sleep forever. Taking the lock on the write side prevents this from occuring.

Note also that many uses of condition variables do more than just modifying a flag in the lock - they may manipulate linked lists, for example, or some other complex data structure. In this case, the lock is needed to protect that data structure, as well as for the condition variable.

0
votes

You're doing it wrong. condition variables have a mutex associated with them. You need to lock the mutex before changing the variable and releasing it afterwards.

There is no dead lock - pthread_cond_wait gets the associated mutex as parameter exactly because so it can unlock the mutex when you are block in a race free manner (it releases the mutex when you are on the waiters queue for the condition variable, so that you are granteed to be awaken when the condition variable is signaled.