Semaphores

Solving the readers & writers problem

We can solve this problem using---guess what---semaphores. The approach is to have one mutual exclusion semaphore for the database as a whole. Essentially though, all the readers share the same critical section, that is, only the first reader does a WAIT on the database mutex semaphore. All subsequent readers notice that another reader has locked the database, and proceed to read. When the last reader has finished, it 'leaves' the critical section by performing a SIGNAL on the semaphore. It's like: last reader out switches off the light.

Any writer process must protect its critcial section by WAITing and SIGNALing as normal (since it may not share the database with readers, nor with other writers).

Since the readers must keep track of how many of them there are, they share an integer counter variable (called 'numberOfReaders'), which must also be protected by a semaphore.

So the variables shared by all readers and writers are...

Semaphore databaseMutex = new Semaphore(1);    // Binary semaphores again.
Semaphore readersMutex = new Semaphore(1);
integer numberOfReaders = 0;
The code for a writer is pretty simple, so let's look at that first:
void write(some stuff){
    databaseMutex.wait();
    // Write some stuff to the database.
    databaseMutex.signal();
}

As you can see, it's standard mutual exclusion. The code for the readers, however, must only lock the 'databaseMutex' if it is the first reader, and must only unlock the 'databaseMutex' if it is the last reader (allowing for other readers to come and go while we are reading).

resulttype read(some thing){
    readersMutex.wait();
    numberOfReaders += 1;
    if (numberOfReaders == 1) databaseMutex.wait();
    readersMutex.signal();

    // Read something from database.

    readersMutex.wait();
    if (numberOfReaders == 1) databaseMutex.signal();
    numberOfReaders -= 1;
    readersMutex.signal();
    return result;
}

We must check when leaving the reading routine whether we were the last to leave. It does not stand to reason that the same reader that locked the database is the one to unlock it. We may be the first reader, but other readers join while we are reading, and they are still reading after we leave. Someone else can take the responsibility of unlocking the database again.


last updated 1998