The writer thread must block (wait) when the shared buffer is full
The reader thread must block (wait) when the shared buffer is empty
nItems = 0 buf: 0 1 2 3 4 ... N-1 +---+---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+ |
|
The pointers are initialized as follows:
nItems = 0 buf: 0 1 2 3 4 ... N-1 +---+---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+ ^ | readPtr writePtr |
nItems = 1 buf: 0 1 2 3 4 ... N-1 +---+---+---+---+---+---+---+---+---+---+---+ | x | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+ ^ ^ | | readPtr | | writePtr |
nItems = 4 buf: 0 1 2 3 4 ... N-1 +---+---+---+---+---+---+---+---+---+---+---+ | x | x | x | x | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+ ^ ^ | | readPtr | | writePtr |
(Notice that the writePtr always points to the next empty slot.
The readPtr is on the next available item for reading)
nItems = 3 buf: 0 1 2 3 4 ... N-1 +---+---+---+---+---+---+---+---+---+---+---+ | | x | x | x | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+ ^ ^ | | readPtr | | writePtr |
|
Shared variables: int MAX; int nItems = 0; // Number of items in buffer int buf[MAX]; |
1. Reader starts first 2. Reader locks the mutex 3. Reader finds buffer empty 4. Reader blocks 5. Writer starts 6. Writer tries to lock the mutex 7. Write blocks too |
The system is now dead locked because the writer cannot put an item in the buffer to release the reader
|
(Because if we fill the last empty slot, we will no be able to distinguish the filled state from the empty state)
writePtr == readPtr |
(writePtr+1)%N == readPtr |
Shared variables: int MAX; int nItems = 0; // Number of items in buffer int buf[MAX]; |
1. Reader starts first 2. Reader finds buffer empty (readPtr == writePtr) 3. Reader blocks 4. Writer starts 5. Writer write an item to buffer 6. Writer detects a BLOCKED reader and UNBLOCKS the reader... |
Problem solved... or so it seems :-)
But creating a blocking situation is very subtle....
1. Reader starts first 2. Reader finds buffer empty (readPtr == writePtr) (Notice that the reader used writePtr from the writer !) 3. Writer starts !!! 4. Writer detects buffer not filled 5. Writer writes an item (The writePtr value read by the reader is now incorrect !!!) 4. Writer again detects buffer not filled 5. Writer again writes an item .... and so on until buffer is filled completely (All the while, the reader did not progress, so reader is NOT BLOCKED) k. Writer fills up the buffer and blocks k+1. NOW, the Reader finally progresses and BLOCKS |
The system is now dead locked ---- because both reader and writer processes are blocked.
|
Any thread can perform operations on a semaphore
Here is a picture of a "real life" semaphore:
![]() |
A semaphore is places at the entrance of stretch of single-tracked rail:
![]() |
So there can only be one train traveling on the stretch of rail !!!
(Older semaphores will only cause the signal at the other end to set to the danger state and the conductor must manually stop the train....)
|
Example:
semaphore s(10); // s.count is set to 10 |
|
Furthermore: the P(s) and V(s) operations are atomic
That means all the effects of each operations are completed without any interruption (no intervening action of any kind).
Example code used to access a shared variable:
int x; // shared variable semaphore s(1); // shared semaphore variable thread i: ..... P(s); x = x + 1; V(s); |
Because the semaphore is initialed to one, the number of times that P(s) will succeed is one time only.
Therefore, only one thread can pass P(s) at any time...
Mutual exclusion is ensured !
Shared variables: int MAX (some given unspecified constant); int nItems = 0; // Number of items in buffer int buf[MAX]; semaphore writerSem(MAX); // MAX writer credits: let writer in MAX times semaphore readerSem(0); // 0 reader credits: block reader from entry |
Why it will work correctly:
|
How to run the program:
|