Thread Synchronisation Problems
Thread Synchronisation Problems
problems
Module 4 self study material
Bounded buffer
Reader and writers
Priority inversion
★ Priority inversion
Bounded
buffer
Bounded buffer
A bounded buffer lets multiple producers and multiple
consumers share a single buffer. Producers write data to
the buffer and consumers read data from the buffer.
★ Producers must block if the buffer is full.
★ Consumers must block if the buffer is empty.
multiple multiple
producers consumers
Implementation
Use an array of size N to store the data items in the buffer.
next_in = 0 next_out = 0
multiple multiple
! ! !
producers consumers
0 1 2 3 4 N-1
The next_in index must be incremented after every write
to the buffer.
next_in = 1 next_out = 0
A A ! ! !
0 1 2 3 4 N-1
next_in = 2 next_out = 0
B A B ! ! !
0 1 2 3 4 N-1
next_in = 3 next_out = 0
C A B C ! ! !
0 1 2 3 4 N-1
The next_out index must be incremented after every read
from the buffer.
next_in = 3 next_out = 1
A B C ! ! ! A
0 1 2 3 4 N-1
next_in = 3 next_out = 2
B C ! ! ! B
0 1 2 3 4 N-1
next_in = 4 next_out = 2
D C D ! ! !
0 1 2 3 4 N-1
The buffer wraps around in a circular manner.
Producer
next_in = (next_in + 1) % N
Consumer
next_out = (next_out + 1) % N
Mutual exclusion
All updates to the buffer state must be done in a critical
section. More specifically, mutual exclusion must be
enforced between the following critical sections:
Use one semaphore named empty to count the empty slots in the buffer.
Use one semaphore named data to count the number of data items in the
buffer.
‣ Initialise this semaphore to 0.
‣ A consumer must wait on this semaphore before reading from the
buffer.
‣ A producer will signal this semaphore after writing to the buffer.
P producers and C consumers using a shared bounded
buffer of size N. Producers writes to buffer at index
next_in and consumer reads at index next_out.
Shared resources
0 0 1 0 N
signal(mutex) signal(mutex)
signal(data) signal(empty)
} }
A pipe is a bounded buffer
ls | grep .txt | wc
Concurrent writes to a pipe
Is a single write to a pipe atomic, i.e., is the whole amount written in a single
write operation not interleaved with data written by any other process?
POSIX.1-200
• Using write() to write less than PIPE_BUF bytes must be atomic:
the output data is written to the pipe as a contiguous sequence.
• Writes of more than PIPE_BUF bytes may be nonatomic: the kernel
may interleave the data, on arbitrary boundaries, with data written by
other processes.
The value if PIPE_BUF is defined by each implementation, but the
minimum is 512 bytes (see limits.h).
On Linux:
• PIPE_BUF = 4096.
• The value of PIPE_BUF is a consequence of other logic in the kernel,
it is not a configuration parameter.
Readers
and writers
Readers-Writers Problem
A data set is shared among a number of concurrent
processes. Readers only read the data set; they do not
perform any updates. Writers can both read and write.
Only one single writer can access the shared data at the same time, any other
writers or readers must be blocked.
W
R R R R R R
Allow multiple readers to read at the same time, any writers must be blocked
R
R R R R
R readers and W writers access the same shared data set.
Allow multiple readers to read at the same time.
Only one single writer can access the shared data at the
same time.
Shared
Semaphores used to synchronize Integer
readers and wirters
Shared data Mutual exclusion Mutual exclusive Count the number
among writers. updates of readcount of active readers.
accessed by
readers and
wrt mutex readcount
writers
1 1 0
reacount--;
// Write shared data if readcount == 0:
signal(wrt);
signal(wrt); signal(mutex);
} }
Priority
inversion
Scenario (1)
A high priority task H is blocked due to a low priority task L
holding a shared resource R (for example a binary semaphore)
task H wants to acquire.
1) Consider two tasks H and L, of high and low priority respectively, either of
which can acquire exclusive use of a shared resource R.
2) L acquires R.
3) If H attempts to acquire R after L has acquired it, then H becomes blocked
until L relinquishes the resource.
L holds R
L holds R
★ That is, the higher-priority job M must wait for the critical section of the
lower priority job L to be executed, because L has inherited H's priority.
★ When L exits its critical section, it regains its original (low) priority and
awakens H (which was blocked by L).