Synchronization
Synchronization
Textbook Ch6
These slides were compiled from the OSC textbook slides (Silberschatz, Galvin,
and Gagne) and the instructor’s class materials.
CSS430 Processes
Synchronization 1
CSS430 Processes
Synchronization 2
Revisiting Bounded Buffer
public void enter( Object item ) {
while ( count == BUFFER_SIZE )
roducer Process
; // buffer is full! Wait till buffer is consumed
or(int i = 0; ; i++ ) {
++count; Dissect it !!
buffer[in] = item; // add an item
BoundedBuffer.enter(new Integer(i));
in = ( in + 1 ) % BUFFER_SIZE;
}
for(int i = 0; ; i++ ) {
out in BoundedBuffer.remove();
CSS430 Processes
}
Synchronization 3
Race Condition
++count: Producer: reg1 = mem[count]; {reg1=5}
reg1 = mem[count]; Producer: reg1 = reg1 + 1; {reg1=6}
reg1 = reg1 + 1; Consumer: reg2 = mem[count]; {reg2=5}
mem[count] = reg1; Consumer: reg2 = reg2 – 1; {reg2=4}
-- count: Producer: mem[count] = reg1; {count=6}
reg2 = mem[count]; Consumer: mem[count] = reg2; {count=4
reg2 = reg2 – 1;
mem[count] = reg2;
It works only for a pair of threads. How about a mutual
execution among three or more threads? Check
Lamport’s Algorithm (See Appendix).
Interrupt Masking:
It disables even time interrupts, thus not allowing
preemption. Malicious user program may hog CPU
forever.
Hardware solutions:
Atomic (non-interruptible) set of instructions provided
Test-and-set (or read-modify-write)
Swap
They are an atomic combination of memory read and
CSS430 Processes
Synchronization 15
Thread Using Swap
HardwareData lock = new HardwareData(false); // a shared lock 1st Process 2nd Process
HardwareData key = new HardwareData(true); // my key
key key
while (true) { true false true
key.set(true); // my key is now true
do {
I got it!
lock.swap(key); 1st swap 2nd swap
// my key got lock’s content.
} while (key.get() == true); // this means lock was true locked!
criticalSection( ); // now in critical section code
lock.set(false); Lock
nonCriticalSection( ); // out of critical section false true
}
CSS430 Processes
Synchronization 16
Semaphore
Synchronization tool that does not require busy waiting at a
user level
Semaphore S – integer variable
Two standard operations modify S: acquire() and release()
Originally called P() and V()
Less complicated
Can only be accessed
acquire( ) { P (atomic)Voperations
via two indivisible
while value <= 0
; // no-op
value--;
} P V
release( ) {
value++; P V
wakeup( );
}
CSS430 Processes
Synchronization 17
Thread Using Semaphore
public class Worker implements Runnable {
private Semaphore sem;
private String name;
public Worker(Semaphore sem, String name) {
this.sem = sem;
this.name = name;
}
public void run() {
while (true) {
sem.acquire();
MutualExclusionUtilities.criticalSection(name);
sem.release();
MutualExclusionUtilities.nonCriticalSection(name);
} } }
public class SemaphoreFactory { Bee
public static void main(String args[]) {
Semaphore sem = new Semaphore(1); Bee
Thread[] bees = new Thread[5];
for (int i = 0; i < 5; i++)
Bee P V
bees[i] = new Thread( Bee Bee
new Worker(sem,
"Worker " + (new Integer(i)).toString() ));
for (int i = 0; i < 5; i++)
bees[i].start();
} } CSS430 Processes
Synchronization 18
Semaphore Eliminating
Busy-Waiting
Waiting List
acquire(S){
Bee
value--;
if (value < 0) {
Bee
add this process to list
block;
Bee P V
}
}
Bee Bee
release(S){
value++; Waiting List
if (value <= 0) {
remove a process P from list
Bee Wake up one
}
wakeup(P);
Bee
}
Bee P V
Bee Bee
CSS430 Processes
Synchronization 19
Discussion 1
1. Non-interruptible execution of CPU instructions is not enough to
implement TestAndSet and Swap. Why? What else should hardware
support?
CSS430 Processes
Synchronization 20
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
P(S); P(Q);
P(Q); P(S);
V(Q); V(S);
V(S); V(Q);
Starvation – indefinite blocking. A process may never be
removed from the semaphore queue in which it is suspended.
What if processes are waiting at P(S) in LIFO order
CSS430 Processes
Synchronization 21
Classical problem 1:
Bounded-Buffer Problem
public class BoundedBuffer {
public BoundedBuffer( ) {
// buffer is initially empty
in = 0; out = 0;
buffer = new Object[BUFFER_SIZE]; // Shared buffer can store five objects.
mutex = new Semaphore( 1 ); // mutex allows only one thread to enter
empty = new Semaphore(BUFFER_SIZE); // empty blocks producer while empty=0
full = new Semaphore( 0 ); // full blocks consumer while full=0
} producer consume
public void insert( ) { /* see next slides */ } empty.P( ) full.P( )
public Object remove( ) { /* see next slides */ }
mutex.P(
(empty--)
)
(full--)
private static final int BUFFER_SIZE = 5; signal signal
private Semaphore mutex, empty, full;
private int in, out;
private Object[] buffer;
mutex.V( )
full.V( ) empty.V( )
} (full++)
CSS430 Processes (empty++)
Synchronization 22
Enter and Remove
methods
public void insert(Object item) {
empty.acquire(); // blocked while empty = 0
mutex.acquire(); // blocked while someone is using mutex, (i.e., in CS)
// add an item to the buffer this is CS
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
mutex.release(); // releasing mutex, (i.e., exited from CS)
full.release(); // increment full
}
public Object remove( ) {
full.acquire(); // blocked while full = 0
mutex.acquire(); // blocked while someone is using mutex,
(I.e., in CS)
// remove an item from the buffer this is CS
Object item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
mutex.release(); // releasing mutex, (i.e., exited from CS)
empty.release(); // increment empty
return item; CSS430 Processes
Synchronization 23
}
Producer and Consumer
Threads
import java.util.Date;
public class Producer implements Runnable {
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
Date message;
while (true) {
// nap for awhile
SleepUtilities.nap();
// produce an item & enter it into the buffer
message = new Date();
buffer.insert(message);
} } }
public class Consumer implements Runnable {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
Date message;
while (true) {
// nap for awhile
SleepUtilities.nap();
// consume an item from the buffer
message = (Date)buffer.remove();
} } }
CSS430 Processes
Synchronization 24
Bounded Buffer Problem:
Factory
CSS430 Processes
Synchronization 25
Monitors
Entry
queue p6 p7 p8
X: p2 p4 p1 High-level language construct
Y: p3 p5 Only one process allowed in a monitor, thus
executing its method
MethodA A process in the monitor can wait on a
MethodB
MethodC condition variable, say x, thus relinquishing the
x.wait( ); monitor and allowing another process to enter
A process can signal another process waiting
p1 on a condition variable (on x).
x.signal( ) A process signaling another process should exit
from the monitor, because the signal process
may have begun to work in the monitor.
CSS430 Processes
Synchronization 26
Java Synchronization
public class ClassA { // Every object has a lock associated with it.
public synchronized void method1( ) { // Calling a synchronized method requires “owning” the
lock.
….;
// The lock is released when a thread exits the synchronized method.
}
public Synchronized void method2( ) { // If a calling thread does not own the lock it is placed in
the entry set.
}
private data a, b, c; CSS430 Processes
} Synchronization 27
Java Monitor
public void synchronized method1( ) { // Calling a synchronized method requires “owning” the lock.
// If a calling thread does not own the lock it is placed in the entry s
while ( condition == false )
try {
wait( ); // The thread releases a lock and places itself in the wait set.
} catch( InterruptedException e ) { }
}
….;
notify( ); // The calling thread resumes one of threads waiting in the wait set
}
CSS430 Processes
Synchronization 28
Enter and Remove with
Java Synchronization
Producer Consumer
Public synchronized void insert( Object item ) { Public synchronized Object remove( ) {
while ( count == BUFFER_SIZE ) while ( count == 0 )
try { try {
wait( ); wait( );
} catch ( InterruptedException e ) { } } catch ( InterruptedException e ) { }
} }
++count; CS --count;
buffer[in] = item; item = buffer[out];
in = ( in + 1 ) % BUFFER_SIZE; out = ( out + 1 ) % BUFFER_SIZE;
notify( ); notify( );
} return item;
}
CSS430 Processes
Synchronization 29
Classical Problem 2:
The Readers-Writers
Problem
Multiple readers or a single writer can use DB.
X X X
writer reader writer reader
reader
writer reader
reader
reader
writer
reader reader
CSS430 Processes
Synchronization 30
Database
public class Database implements RWLock {
public Database( ) {
readerCount = 0; // # readers in database access
dbWriting = false; // a writer in database modification
}
public synchronized void acquireReadLock( ) {
/* A reader can start reading if dbWritng == false */ }
public synchronized void releaseReadLock( ) {
/* A reader exits from database, as waking up a thread */ }
public synchronized void acquireWriteLock( ) {
/* A writer can start writing if dbReading and dbWriting == false */ }
public synchronized void releaseWriteLock( ) {
/* A writer can exit from database, as waking up a thread */ }
private int readerCount;
private boolean dbWriting;
} CSS430 Processes
Synchronization 31
Readers
Condition reader, writer; // introduce condition variables
public synchronized void acquireReadLock( ) {
while (dbWriting == true) {|| !writer.isEmpty(
// while a writer is)in) DB,
{ I have to wait.
try {
reader.wait(
wait( );
) (InterruptedException e) { }
} catch
}
++readerCount;
}
CSS430 Processes
Synchronization 32
Writers
Public synchronized void ackquireWriteLock( ) {
while (readerCount > 0 || dbWriting == true) // while reader(s) or another write is in DB
try {
wait( );
writer.wait( ) // I have to wait.
} catch ( InterruptedException e ) { }
}
dbWriting = true; // Tell all others that DB is in write.
}
THINKING
HUNGRY
EATING
Shared data
Semaphore chopStick[] = new Semaphore[5];
CSS430 Processes
Synchronization 34
The Structure of
Philosopher i
Philosopher i
while ( true ) {
// get left chopstick
chopStick[i].P();
// get right chopstick
chopStick[(i + 1) %
5].P();
CSS430 Processes
Synchronization 37
Discussions 2
1. What is the main merit of notifyAll( ) in the
readers-writers problem?
CSS430 Processes
Synchronization 39
Appendix
Lamport’s Algorithm
Available for two or more processes
bool enter[n]; for ( int i = 0; i < n; i++ ) enter[n] = false;
int priority[n]; for ( int i = 0; i < n; i++ ) priority = 0;
Process i:
enter[i] = true;
priority[i] = 1 + max( priority[0], …, priority[n-1] ); // a higher number is a lower priority
enter[i] = false;
// critical section
priority[i] = 0;