Operating System 2
Operating System 2
PROCESS SYNCHRONIZATION
05/17/25
Process Synchronization
• Background
• The Critical-Section Problem
• Synchronization Hardware
• Semaphores
• Classical Problems of Synchronization
05/17/25
Background
• Concurrent access to shared data may result in data
inconsistency.
• Maintaining data consistency requires mechanisms to
ensure the orderly execution of cooperating processes.
• Shared-memory solution to bounded-butter problem
(Chapter 4) allows at most n – 1 items in buffer at the
same time. A solution, where all N buffers are used is
not simple.
– Suppose that we modify the producer-consumer code by
adding a variable counter, initialized to 0 and incremented
each time a new item is added to the buffer
05/17/25
Bounded-Buffer
#define BUFFER_SIZE 10
typedef struct {
...
} item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
int counter = 0;
05/17/25
Bounded-Buffer
• Producer process
item nextProduced;
while (1) {
while (counter == BUFFER_SIZE)
; /* do nothing */
buffer[in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
counter++;
}
05/17/25
Bounded-Buffer
• Consumer process
item nextConsumed;
while (1) {
while (counter == 0)
; /* do nothing */
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
counter--;
}
05/17/25
Bounded Buffer
• The statements
counter++;
counter--;
05/17/25
Bounded Buffer
• The statement “count++” may be implemented in
machine language as:
register1 = counter
register1 = register1 + 1
counter = register1
05/17/25
Bounded Buffer
• If both the producer and consumer attempt to
update the buffer concurrently, the assembly
language statements may get interleaved.
05/17/25
Bounded Buffer
• Assume counter is initially 5. One interleaving of
statements is:
producer: register1 = counter (register1 = 5)
producer: register1 = register1 + 1 (register1 = 6)
consumer: register2 = counter (register2 = 5)
consumer: register2 = register2 – 1 (register2 = 4)
producer: counter = register1 (counter = 6)
consumer: counter = register2 (counter = 4)
05/17/25
Race Condition
• Race condition: The situation where several
processes access – and manipulate shared
data concurrently. The final value of the
shared data depends upon which process
finishes last.
05/17/25
The Critical-Section Problem
• n processes all competing to use some shared
data
• Each process has a code segment, called critical
section, in which the shared data is accessed.
• Problem – ensure that when one process is
executing in its critical section, no other
process is allowed to execute in its critical
section.
05/17/25
Solution to Critical-Section Problem
1.Mutual Exclusion. If process Pi is executing in
its critical section, then no other processes can
be executing in their critical sections.
2.Progress. If no process is executing in its
critical section and there exist some processes
that wish to enter their critical section, then
the selection of the processes that will enter
the critical section next cannot be postponed
indefinitely.
05/17/25
Bounded Waiting.
A bound must exist on the number of times
that other processes are allowed to enter their
critical sections after a process has made a
request to enter its critical section and before
that request is granted.
Assume that each process executes at a nonzero
speed
No assumption concerning relative speed of the n
processes.
05/17/25
Initial Attempts to Solve Problem
• Only 2 processes, P0 and P1
• General structure of process Pi (other process Pj)
do {
entry section
critical section
exit section
reminder section
} while (1);
• Processes may share some common variables to
synchronize their actions.
05/17/25
Semaphores
• Synchronization tool that does not require busy
waiting.
• Semaphore S – integer variable
• can only be accessed via two indivisible (atomic)
operations
wait (S):
while S 0 do no-op;
S--;
signal (S):
S++;
05/17/25
Semaphore Implementation
• Define a semaphore as a record
typedef struct {
int value;
struct process *L;
} semaphore;
05/17/25
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);
• Starvation – indefinite blocking. A process may never be removed
from the semaphore queue in which it is suspended
05/17/25
Two Types of Semaphores
• Counting semaphore – integer value can range
over an unrestricted domain.
• Binary semaphore – integer value can range
only between 0 and 1; can be simpler to
implement.
• Can implement a counting semaphore S as a
binary semaphore.
05/17/25
Implementing S as a Binary Semaphore
• Data structures:
binary-semaphore S1, S2;
int C:
• Initialization:
S1 = 1
S2 = 0
C = initial value of semaphore
S
05/17/25
Classical Problems of Synchronization
• Bounded-Buffer Problem
• Dining-Philosophers Problem
05/17/25
Bounded-Buffer Problem
• Shared data
Initially:
05/17/25
Bounded-Buffer Problem Producer
Process
do {
…
produce an item in nextp
…
wait(empty);
wait(mutex);
…
add nextp to buffer
…
signal(mutex);
signal(full);
} while (1);
•
05/17/25
Bounded-Buffer Problem Consumer
Process
do {
wait(full)
wait(mutex);
…
remove an item from buffer to nextc
…
signal(mutex);
signal(empty);
…
consume the item in nextc
…
} while (1);
05/17/25
Readers-Writers Problem
• Shared data
Initially
05/17/25
Readers-Writers Problem Writer
Process
wait(wrt);
…
writing is performed
…
signal(wrt);
05/17/25
Dining-Philosophers Problem
Shared data
semaphore chopstick[5];
Initially all values are 1
05/17/25
Dining-Philosophers Problem
• Philosopher i:
do {
wait(chopstick[i])
wait(chopstick[(i+1) % 5])
…
eat
…
signal(chopstick[i]);
signal(chopstick[(i+1) % 5]);
…
think
…
} while (1);
05/17/25