ch5 New
ch5 New
Synchronization
Process Synchronization
• Background
• The Critical-Section Problem
• Peterson’s Solution
• Synchronization Hardware
• Mutex Locks
• Semaphores
• Classic Problems of Synchronization
• Monitors
Background
• Processes can execute concurrently
– May be interrupted at any time, partially completing execution
• Concurrent access to shared data may result in data inconsistency
• Maintaining data consistency requires mechanisms to ensure the
orderly execution of cooperating processes
• Illustration of the problem:
Suppose that we wanted to provide a solution to the consumer-
producer problem that fills all the buffers. We can do so by having
an integer counter that keeps track of the number of full buffers.
Initially, counter is set to 0. It is incremented by the producer after
it produces a new buffer and is decremented by the consumer after
it consumes a buffer.
Producer
while (true) {
/* produce an item in next produced */
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
test_and_set Instruction
Definition:
boolean test_and_set (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
1. Executed atomically
2. Returns the original value of passed parameter
3. Set the new value of passed parameter to “TRUE”.
Solution using test_and_set()
Shared Boolean variable lock, initialized to FALSE
Solution:
do {
while (test_and_set(&lock))
; /* do nothing */
/* critical section */
lock = false;
/* remainder section */
} while (true);
compare_and_swap Instruction
Definition:
int compare _and_swap(int *value, int expected, int new_value) {
int temp = *value;
if (*value == expected)
*value = new_value;
return temp;
}
1. Executed atomically
2. Returns the original value of passed parameter “value”
3. Set the variable “value” the value of the passed parameter “new_value” but
only if “value” ==“expected”. That is, the swap takes place only under this
condition.
Solution using compare_and_swap
• Shared integer “lock” initialized to 0;
• Solution:
do {
while (compare_and_swap(&lock, 0, 1) != 0)
; /* do nothing */
/* critical section */
lock = 0;
/* remainder section */
} while (true);
Mutex Locks
Previous solutions are complicated and generally inaccessible to
application programmers
OS designers build software tools to solve critical section problem
Simplest is mutex lock
Protect a critical section by first acquire() a lock then release() the
lock
Boolean variable indicating if lock is available or not
Calls to acquire() and release() must be atomic
Usually implemented via hardware atomic instructions
But this solution requires busy waiting
This lock therefore called a spinlock
Binary Semaphores is called as Mutex Lock
acquire() and release()
• acquire() {
while (!available)
; /* busy wait */
available = false;
}
• release() {
available = true;
}
• do {
acquire lock
critical section
release lock
remainder section
} while (true);
acquire() and release()
Semaphore
• A semaphore is a variable or abstract data type used to control access
to a common resource by multiple processes in a concurrent system
such as a multitasking operating system.
wait(semaphore *S) {
S->value--;
if (S->value < 0) {
add this process to S->list;
block();
}
}
signal(semaphore *S) {
S->value++;
if (S->value <=0) {
remove a process P from S->list;
wakeup(P);
}
}
Deadlock and Starvation
• Deadlock – two or more processes are waiting indefinitely for an
event that can be caused by only one of the waiting processes
• Let S and Q be two semaphores initialized to 1
P0 P1
wait(S); wait(Q);
wait(Q); wait(S);
... ...
signal(S); signal(Q);
signal(Q); signal(S);
do {
...
/* produce an item in next_produced */
...
wait(empty);
wait(mutex);
...
/* add next produced to the buffer */
...
signal(mutex);
signal(full);
} while (true);
Bounded Buffer Problem (Cont.)
The structure of the consumer process
Do {
wait(full);
wait(mutex);
...
/* remove an item from buffer to next_consumed */
...
signal(mutex);
signal(empty);
...
/* consume the item in next consumed */
...
} while (true);
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
• Problem – allow multiple readers to read at the same time
– Only one single writer can access the shared data at the
same time
• Several variations of how readers and writers are considered –
all involve some form of priorities
• Shared Data
– Data set
– Semaphore rw_mutex initialized to 1
– Semaphore mutex initialized to 1
– Integer read_count initialized to 0
Readers-Writers Problem
• In the above code, mutex and rw_mutex are semaphores that
are initialized to 1. The mutex semaphore ensures mutual
exclusion and rw_mutex handles the writing mechanism and is
common to the reader and writer process code.
do {
wait(rw_mutex);
...
/* writing is performed */
...
signal(rw_mutex);
} while (true);
Readers-Writers Problem (Cont.)
• The structure of a reader process
do {
wait(mutex);
read_count++;
if (read_count == 1)
wait(rw_mutex);
signal(mutex);
...
/* reading is performed */
...
wait(mutex);
read count--;
if (read_count == 0)
signal(rw_mutex);
signal(mutex);
} while (true);
Dining-Philosophers Problem
// eat
signal (chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// think
} while (TRUE);
• What is the problem with this algorithm?
Dining-Philosophers Problem Algorithm (Cont.)
• Deadlock handling
– Allow at most 4 philosophers to be sitting simultaneously
at the table.
– Allow a philosopher to pick up the forks only if both are
available (picking must be done in a critical section.
– Use an asymmetric solution -- an odd-numbered
philosopher picks up first the left chopstick and then the
right chopstick. Even-numbered philosopher picks up first
the right chopstick and then the left chopstick.
Problems with Semaphores
• Incorrect use of semaphore operations:
monitor monitor-name
{
// shared variable declarations
procedure P1 (…) { …. }
x_count++;
if (next_count > 0)
signal(next);
else
signal(mutex);
wait(x_sem);
x_count--;
Monitor Implementation (Cont.)
if (x_count > 0) {
next_count++;
signal(x_sem);
wait(next);
next_count--;
}
End of Chapter 5