Concurrency in Shared Memory Systems: Synchronization and Mutual Exclusion
Concurrency in Shared Memory Systems: Synchronization and Mutual Exclusion
Memory Systems
Synchronization and Mutual
Exclusion
Processes, Threads,
Concurrency
• Traditional processes are sequential: one
instruction at a time is executed.
• Multithreaded processes may have
several sequential threads that can
execute concurrently.
• Processes (threads) are concurrent if their
executions overlap – start time of one
occurs before finish time of another.
Concurrent Execution
• On a uniprocessor, concurrency occurs
when the CPU is switched from one
process to another, so the instructions of
several threads are interleaved (alternate)
• On a multiprocessor, execution of
instructions in concurrent threads may be
overlapped (occur at same time) if the
threads are running on separate
processors.
Concurrent Execution
• Thread 1 • Thread 2
(2) Move balance to (1) Move balance to
register1 (register = register2 (register =
100) 100)
(4) compare register1 to (3) compare register2 to
withdraw1 withdraw2
(5)register1 = register1 – (6) register2 = register2
withdraw1 (100-50) – withdraw2 (100 – 75)
(7) store register1 in (8) store register2 in
balance (balance = 50) balance (balance = 25)
Example – Uniprocessor
(A possible instruction sequence showing interleaved
execution)
• Thread 1 • Thread 2
– Move balance to
register (Reg. = 100)
P1’s time slice expires – its
state is saved
… – Move balance to reg.
…
P1 is re-scheduled; its state is – balance >= withdraw2
restored (Reg. = 100)
– balance = balance –
– balance = balance – withdraw2 = (100-75)
withdraw1 (100-50)
– Result: balance = 50
Race Conditions
• The previous examples illustrate a race
condition (data race): an undesirable
condition that exists when several
processes access shared data, and
– At least one access is a write and
– The accesses are not mutually exclusive
• Race conditions can lead to inconsistent
results.
Mutual Exclusion
• Mutual exclusion forces serial resource access
as opposed to concurrent access.
• When one thread locks a critical resource, no
other thread can access it until the lock is
released.
• Critical section (CS): code that accesses shared
resources.
• Mutual exclusion guarantees that only one
process/thread at a time can execute its critical
section, with respect to a given resource.
Mutual Exclusion Requirements
• V(S): • V(S):
if some processes are S=S+1
blocked on S queue if (S <= 0)
then unblock a process then move a process
else S = S + 1 from S queue to the
Ready queue
Usage – Mutual Exclusion
• Using a semaphore to enforce mutual exclusion.
P(mutex) // mutex initially = 1
execute CS;
V(mutex)
• Each process that uses a shared resource must
first check (using P) that no other process is in
the critical section and then must use V to
release the critical section.
Bank Problem Revisited
Semaphore S = 1
Thread 1 Thread 2
P(S) P(S)
Move balance to Move balance to
register1 register2
Compare register1 to Compare register2 to
withdraw1 withdraw2
register1 = register1 – register2 = register2 –
withdraw1 withdraw2
Store register1 in Store register2 in
balance balance
V(S) V(S)
Example – Uniprocessor
• Thread 1 • Thread 2
– P(S) S is decremented: S = 0,
T1 continues to execute
– Move balance to
register (Reg. = 100)
T1’s time slice expires – its state – P(S)
is saved Since S = 0, T2 is blocked
…
T1 is re-scheduled; its state is
restored (Reg. = 100)
T2 resumes executing some
– balance = balance – time after T1 executes V(S)
withdraw1 (100-50) – Move balance to reg.
– V(S) (50)
Thread 2 returns to run state, S
remains 0
– balance >= withdraw2
Since !(50>=75), T2 does not
make withdrawal
– V(S)
Since no thread is waiting, S is
set back to 1
Critical Sections are Indivisible
• The effect of mutual exclusion is to make a
critical section appear to be “indivisible” –
much like a hardware instruction. (Recall
the atomic nature of a transaction)
• In the bank example, once T1enters its
critical section no other thread is allowed
to operate on balance until T1 signals it
has left the CS. (assumes that all users
employ mutual exclusion)
Implementing Semaphores:
P and V Must Be Indivisible
Producer: Consumer:
while(true) while(true)
produce v; P(n); // wait for a full buffer
P(e); // wait for buffer slot P(s); // wait for buffer pool
P(s); // wait for buffer pool access
access w:=take();
append(v); V(s); // release buffer pool
V(s); // release buffer pool V(e); // signal an empty buffer
V(n); // signal a full buffer consume(w);
Readers and Writers Problem
• Characteristics:
– concurrent processes access shared data
area (files, block of memory, set of registers)
– some processes only read information, others
write (modify and add) information
• Restrictions:
– Multiple readers may read concurrently, but
when a writer is writing, there should be no
other writers or readers.
Compare to Prod/Cons
• Differences between Readers/Writers
(R/W) and Producer/Consumer (P/C):
– Data in P/C is ordered - placed into buffer and
retrieved according to FIFO discipline. All data
is read exactly once.
– In R/W, same data may be read many times
by many readers, or data may be written by
writer and changed before any reader reads.
No order enforced on reads.
procedure writer; // Initialization code
begin integer readcount = 0; // done only once
repeat semaphore x, wsem = 1; // done only once
P (wsem);
write data; procedure reader;
V (wsem); begin
repeat
forever
P (x);
end;
readcount = readcount + 1;
if readcount = =1 then P (wsem);
V (x);
read data;
P (x);
readcount = readcount - 1;
if readcount == 0 then V(wsem);
V (x);
forever
end;
Any Questions?
Can you think of any real
examples of producer-consumer
or reader-writer situations?
Semaphores and User Thread Library
• Thread libraries can simulate real semaphores.
• In a multi-(user-level) threaded process the OS
only sees a single thread of execution; e.g.,
T1, T1, T1, L, L, T2, T2, L, L, T1, T1, …
– Library functions execute when a u-thread
voluntarily yields control
• Use a variable as a semaphore; access via P
& V functions. A thread executes P(S) and
finds S = 0. Then it yields control.
Semaphores and User Thread Library