theprogrammer
theprogrammer

Reputation: 2007

How do multiple mutex locks work?

I am learning about POSIX threads and my professor has started teaching about the first readers-writers problem. This is the pseudocode I have about solving the problem (only for the first case: reader's preference).

semaphore rw_mutex = 1; /* semaphore common to both reader & writer */
semaphore mutex = 1; /* semaphore for reading (reader lock) */
int read_count = 0; /* track number of readers in CS */


Writer:
do {
lock(rw_mutex);
/* ensure no writer or reader can enter */
...
/* writing is performed */
...
unlock(rw_mutex);
/* release lock */
} while (true);


Reader:
do
{
lock(mutex);
/* first update read_count atomically */
read_count++;
if (read_count == 1) {
lock(rw_mutex);
/* ensure no writer can enter */
}
unlock(mutex);
/* allow other readers to access */
...
/* reading is performed */
...
lock(mutex);
read_count--;if (read_count == 0) unlock(rw_mutex);
/* allow writers after
last reader has left the CS */
unlock(mutex);
/* release lock */
} while(true);

First of all this is my understanding of mutex locks: Once we create a lock and unlock pair, the code between these two entities can only be accessed by a single thread at a time.

Now if my understanding is right, then I can pretty much understand what's happening in the Writer section of the above pseudocode. We are locking and then writing to the shared resource and in the meanwhile, no one can access the shared resource since it's locked and then we simply unlock it.

But I have problems understanding the reader part. If we lock once, it means that it's locked for good until we unlock it again right? In that case, what's the use of locking twice in reader's section?

My main question is this: What does locking mean? and what's the difference between say lock(rw_mutex) and lock(mutex) in the above pseudocode? If once we call a lock, the program should lock it regardless of what parameter we pass in right? So what do these parameters: rw_mutex and mutex mean here? How does multiple mutex locking work?

Upvotes: 1

Views: 12305

Answers (1)

caf
caf

Reputation: 239011

The way to think about mutexes is like this: a mutex is like a token that at any point in time can either be held by one thread, or available for any thread to take.

When a thread calls lock() on a mutex, it is attempting to take the mutex: if the mutex is available ("unlocked") then it will take it straight away, otherwise if it is currently held by another thread ("locked") then it will wait until it is available.

When a thread calls unlock() on a mutex, it is returning a mutex that it currently holds so that it is available for another thread to take.

If you have more than one mutex, each mutex is independent: a thread can hold neither, one or both of them.

In your Reader, a thread first acquires mutex. While mutex is owned by the thread, no other thread can acquire mutex, so no other thread can be executing between either of the lock(mutex); / unlock(mutex); pairs (one at the top of the Reader function and one further down). Because read_count is only ever accessed within such a pair (while mutex is held), we know that only one thread will access read_count at a time.

If the Reader has just incremented read_count from zero to one, it will also acquire the rw_mutex mutex. This prevents any other thread from acquiring that mutex until it has been released, which has the effect of preventing Writer from proceeding into its critical section.

This code effectively passes ownership of the rw_mutex from the thread that locked it in Reader to any remaining readers in the critical section, when that thread leaves the critical section. This is just a matter of the code logic - no actual call is required to do this (and it's only possible because it is using a semaphore to implement rw_mutex, and not for example a pthreads mutex, which must be released by the thread that locked it).

Upvotes: 7

Related Questions