CSC 414 Chapter 7, Spring 2008
Notre Dame University–Louaize · Applied Operating Systems · 71 pages
Showing the first 10 of 71 pages. Download the PDF to see all of it.
More CSC 414 files
Show the text of this chapter
7.1
Applied Operating System Concepts
Module 7: Process Synchronization
• Background
• The Critical-Section Problem
• Synchronization Hardware
• Semaphores
• Classical Problems of Synchronization
• Monitors
• Java Synchronization
• Synchronization in Solaris 2
• Synchronization in Windows NT
7.2
Applied Operating System Concepts
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)
has a race condition on the class data count
7.3
Applied Operating System Concepts
Bounded Buffer
public class BoundedBuffer {
public void enter(Object item) {
// producer calls this method
}
public Object remove() {
// consumer calls this method
}
// potential race condition on count
private volatile int count;
}
7.4
Applied Operating System Concepts
enter() Method
// producer calls this method
public void enter(Object item) {
while (count == BUFFER_SIZE)
; // do nothing
// add an item to the buffer
++count;
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
}
7.5
Applied Operating System Concepts
remove() Method
// consumer calls this method
public Object remove() {
Object item;
while (count == 0)
; // do nothing
// remove an item from the buffer
--count;
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
return item;
}
7.6
Applied Operating System Concepts
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.
3. 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.
7.7
Applied Operating System Concepts
Worker Thread
public class Worker extends Thread {
public Worker(String n, int i, MutualExclusion s) {
name = n;
id = i;
shared = s;
}
public void run() { /* see next slide */ }
private String name;
private int id;
private MutualExclusion shared;
}
7.8
Applied Operating System Concepts
run() Method of Worker Thread
public void run() {
while (true) {
shared.enteringCriticalSection(id);
// in critical section code
shared.leavingCriticalSection(id);
// out of critical section code
}
}
7.9
Applied Operating System Concepts
MutualExclusion Abstract Class
public abstract class MutualExclusion {
public static void criticalSection() {
// simulate the critical section
}
public static void nonCriticalSection() {
// simulate the non-critical section
}
public abstract void enteringCriticalSection(int t);
public abstract void leavingCriticalSection(int t);
public static final int TURN_0 = 0;
public static final int TURN_1 = 1;
}
7.10
Applied Operating System Concepts
Testing Each Algorithm
public class TestAlgorithm
{
public static void main(String args[]) {
MutualExclusion alg = new Algorithm_1();
Worker first = new Worker("Runner 0", 0, alg);
Worker second = new Worker("Runner 1", 1, alg);
first.start();
second.start();
}
}
7.11
Applied Operating System Concepts
Algorithm 1
public class Algorithm_1 extends MutualExclusion {
public Algorithm_1() {
turn = TURN_0;
}
public void enteringCriticalSection(int t) {
while (turn != t)
Thread.yield();
}
public void leavingCriticalSection(int t) {
turn = 1 - t;
}
private volatile int turn;
}
7.12
Applied Operating System Concepts
Algorithm 2
public class Algorithm_2 extends MutualExclusion {
public Algorithm_2() {
flag[0] = false;
flag[1] = false;
}
public void enteringCriticalSection(int t) {
// see next slide
}
public void leavingCriticalSection(int t) {
flag[t] = false;
}
private volatile boolean[] flag = new boolean[2];
}
7.13
Applied Operating System Concepts
Algorithm 2 – enteringCriticalSection()
public void enteringCriticalSection(int t) {
int other = 1 - t;
flag[t] = true;
while (flag[other] == true)
Thread.yield();
}
7.14
Applied Operating System Concepts
Algorithm 3
public class Algorithm_3 extends MutualExclusion {
public Algorithm_3() {
flag[0] = false;
flag[1] = false;
turn = TURN_0;
}
public void enteringCriticalSection(int t) {/* see next slides */ }
public void leavingCriticalSection(int t) {{/* see next slides */ }
private volatile int turn;
private volatile boolean[] flag = new boolean[2];
}
7.15
Applied Operating System Concepts
Algorithm 3 – enteringCriticalSection()
public void enteringCriticalSection(int t) {
int other = 1 - t;
flag[t] = true;
turn = other;
while ( (flag[other] == true) && (turn == other) )
Thread.yield();
}
7.16
Applied Operating System Concepts
Algo. 3 – leavingingCriticalSection()
public void leavingCriticalSection(int t) {
flag[t] = false;
}
7.17
Applied Operating System Concepts
Synchronization Hardware
public class HardwareData {
public HardwareData(boolean v) {
data = v;
}
public boolean get() {
return data;
}
public void set(boolean v) {
data = v;
}
private boolean data;
}
7.18
Applied Operating System Concepts
Test-and-Set Instruction (in Java)
public class HardwareSolution
{
public static boolean testAndSet(HardwareData target) {
HardwareData temp = new HardwareData(target.get());
target.set(true);
return temp.get();
}
}
7.19
Applied Operating System Concepts
Thread using Test-and-Set
HardwareData lock = new HardwareData(false);
while (true) {
while (HardwareSolution.testAndSet(lock))
Thread.yield(); // do nothing
// now in critical section code
lock.set(false);
// out of critical section
}
7.20
Applied Operating System Concepts
Swap instruction
public static void swap(HardwareData a, HardwareData b) {
HardwareData temp = new HardwareData(a.get());
a.set(b.get());
b.set(temp.get());
}
7.21
Applied Operating System Concepts
Thread using Swap
HardwareData lock = new HardwareData(false);
HardwareData key = new HardwareData(true);
while (true) {
key.set(true);
do {
HardwareSolution.swap(lock,key);
} while (key.get() == true);
// now in critical section code
lock.set(false);
// out of critical section
}
7.22
Applied Operating System Concepts
Semaphore
• Synchronization tool that does not require busy waiting.
• Semaphore S – integer variable
• can only be accessed via two indivisible (atomic) operations
P (S): while S 0 do no-op;
S--;
V(S): S++;
7.23
Applied Operating System Concepts
Semaphore as General Synchronization Tool
Semaphore S; // initialized to 1
P(S);
CriticalSection()
V(S);
7.24
Applied Operating System Concepts
Semaphore Eliminating Busy-Waiting
P(S) {
value--;
if (value < 0) {
add this process to list
block
}
}
V(S) {
value++;
if (value <= 0) {
remove a process P from list
wakeup(P);
}
}
7.25
Applied Operating System Concepts
Synchronization Using Semaphores
public class FirstSemaphore {
public static void main(String args[]) {
Semaphore sem = new Semaphore(1);
Worker[] bees = new Worker[5];
for (int i = 0; i < 5; i++)
bees[i] = new Worker(sem, "Worker " + (new Integer(i)).toString() );
for (int i = 0; i < 5; i++)
bees[i].start();
}
}
7.26
Applied Operating System Concepts
Worker Thread
public class Worker extends Thread {
public Worker(Semaphore) { sem = s;}
public void run() {
while (true) {
sem.P();
// in critical section
sem.V();
// out of critical section
}
}
private Semaphore sem;
}
7.27
Applied Operating System Concepts
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(S);
V(Q);
V(Q)
V(S);
• Starvation – indefinite blocking. A process may never be
removed from the semaphore queue in which it is suspended.
7.28
Applied Operating System Concepts
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.
7.29
Applied Operating System Concepts
Classical Problems of Synchronization
• Bounded-Buffer Problem
• Readers and Writers Problem
• Dining-Philosophers Problem
7.30
Applied Operating System Concepts
Bounded-Buffer Problem
public class BoundedBuffer {
public BoundedBuffer() { /* see next slides */ }
public void enter() { /* see next slides */ }
public Object remove() { /* see next slides */ }
private static final int BUFFER_SIZE = 2;
private Semaphore mutex;
private Semaphore empty;
private Semaphore full;
private int in, out;
private Object[] buffer;
}
7.31
Applied Operating System Concepts
Bounded Buffer Constructor
public BoundedBuffer() {
// buffer is initially empty
count = 0;
in = 0;
out = 0;
buffer = new Object[BUFFER_SIZE];
mutex = new Semaphore(1);
empty = new Semaphore(BUFFER_SIZE);
full = new Semaphore(0);
}
7.32
Applied Operating System Concepts
enter() Method
public void enter(Object item) {
empty.P();
mutex.P();
// add an item to the buffer
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
mutex.V();
full.V();
}
7.33
Applied Operating System Concepts
remove() Method
public Object remove() {
full.P();
mutex.P();
// remove an item from the buffer
Object item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
mutex.V();
empty.V();
return item;
}
7.34
Applied Operating System Concepts
Readers-Writers Problem: Reader
public class Reader extends Thread {
public Reader(Database db) {
server = db;
}
public void run() {
int c;
while (true) {
c = server.startRead();
// now reading the database
c = server.endRead();
}
}
private Database
server;
}
7.35
Applied Operating System Concepts
Readers-Writers Problem: Writer
public class Writer extends Thread {
public Writer(Database db) {
server = db;
}
public void run() {
while (true) {
server.startWrite();
// now writing the database
server.endWrite();
}
}
private Database
server;
}
7.36
Applied Operating System Concepts
Readers-Writers Problem (cont)
public class Database
{
public Database() {
readerCount = 0;
mutex = new Semaphore(1);
db = new Semaphore(1);
}
public int startRead() { /* see next slides */ }
public int endRead() { /* see next slides */ }
public void startWrite() { /* see next slides */ }
public void endWrite() { /* see next slides */ }
private int readerCount; // number of active readers
Semaphore mutex; // controls access to readerCount
Semaphore db; // controls access to the database
}
7.37
Applied Operating System Concepts
startRead() Method
public int startRead() {
mutex.P();
++readerCount;
// if I am the first reader tell all others
// that the database is being read
if (readerCount == 1)
db.P();
mutex.V();
return readerCount;
}
7.38
Applied Operating System Concepts
endRead() Method
public int endRead() {
mutex.P();
--readerCount;
// if I am the last reader tell all others
// that the database is no longer being read
if (readerCount == 0)
db.V();
mutex.V();
return readerCount;
}
7.39
Applied Operating System Concepts
Writer Methods
public void startWrite() {
db.P();
}
public void endWrite() {
db.V();
}
7.40
Applied Operating System Concepts
Dining-Philosophers Problem
• Shared data
Semaphore chopStick[] = new Semaphore[5];
7.41
Applied Operating System Concepts
Dining-Philosophers Problem (Cont.)
• Philosopher i:
while (true) {
// get left chopstick
chopStick[i].P();
// get right chopstick
chopStick[(i + 1) % 5].P();
// eat for awhile
//return left chopstick
chopStick[i].V();
// return right chopstick
chopStick[(i + 1) % 5].V();
// think for awhile
}
7.42
Applied Operating System Concepts
Monitors
• A monitor is a high-level abstraction that provides thread safety.
• Only one thread may be active within the monitor at a time.
monitor monitor-name
{
// variable declarations
public entry p1(…) {
…
}
public entry p2(…) {
…
}
}
7.43
Applied Operating System Concepts
Condition Variables
• condition x, y;
• A thread that invokes x.wait is suspended until another thread
invokes x.signal
7.44
Applied Operating System Concepts
Monitor with condition variables
7.45
Applied Operating System Concepts
Solution to Dining Philosophers
monitor diningPhilosophers {
int[] state = new int[5];
static final int THINKING = 0;
static final int HUNGRY = 1;
static final int EATING = 2;
condition[] self = new condition[5];
public diningPhilosophers {
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
public entry pickUp(int i) { /* see next slides */ }
public entry putDown(int i) { /* see next slides */ }
private test(int i) {/* see next slides */ }
}
7.46
Applied Operating System Concepts
pickUp() Procedure
public entry pickUp(int i) {
state[i] = HUNGRY;
test(i);
if (state[i] != EATING)
self[i].wait;
}
7.47
Applied Operating System Concepts
putDown() Procedure
public entry putDown(int i) {
state[i] = THINKING;
// test left and right neighbors
test((i + 4) % 5);
test((i + 1) % 5);
}
7.48
Applied Operating System Concepts
test() Procedure
private test(int i) {
if ( (state[(i + 4) % 5] != EATING) &&
(state[i] == HUNGRY) &&
(state[(i + 1) % 5] != EATING) ) {
state[i] = EATING;
self[i].signal;
}
}
7.49
Applied Operating System Concepts
Java Synchronization
• Synchronized, wait(), notify() statements
• Multiple Notifications
• Block Synchronization
• Java Semaphores
• Java Monitors
7.50
Applied Operating System Concepts
synchronized Statement
• Every object has a lock associated with it.
• Calling a synchronized method requires “owning” the lock.
• If a calling thread does not own the lock (another thread already
owns it), the calling thread is placed in the wait set for the
object’s lock.
• The lock is released when a thread exits the synchronized
method.
7.51
Applied Operating System Concepts
Entry Set
7.52
Applied Operating System Concepts
synchronized enter() Method
public synchronized void enter(Object item) {
while (count == BUFFER_SIZE)
Thread.yield();
++count;
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
}
7.53
Applied Operating System Concepts
synchronized remove() Method
public synchronized Object remove() {
Object item;
while (count == 0)
Thread.yield();
--count;
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
return item;
}
7.54
Applied Operating System Concepts
The wait() Method
• When a thread calls wait(), the following occurs:
- the thread releases the object lock.
- thread state is set to blocked.
- thread is placed in the wait set.
7.55
Applied Operating System Concepts
Entry and Wait Sets
7.56
Applied Operating System Concepts
The notify() Method
• When a thread calls notify(), the following occurs:
- selects an arbitrary thread T from the wait set.
- moves T to the entry set.
- sets T to Runnable.
T can now compete for the object’s lock again.
7.57
Applied Operating System Concepts
enter() with wait/notify Methods
public synchronized void enter(Object item) {
while (count == BUFFER_SIZE)
try {
wait();
}
catch (InterruptedException e) { }
}
++count;
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
notify();
}
7.58
Applied Operating System Concepts
remove() with wait/notify Methods
public synchronized Object remove() {
Object item;
while (count == 0)
try {
wait();
}
catch (InterruptedException e) { }
--count;
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
notify();
return item;
}
7.59
Applied Operating System Concepts
Multiple Notifications
• notify() selects an arbitrary thread from the wait set. *This may
not be the thread that you want to be selected.
• Java does not allow you to specify the thread to be selected.
• notifyAll() removes ALL threads from the wait set and places
them in the entry set. This allows the threads to decide among
themselves who should proceed next.
• notifyAll() is a conservative strategy that works best when
multiple threads may be in the wait set.
7.60
Applied Operating System Concepts
Reader Methods with Java
Synchronization
public class Database {
public Database() {
readerCount = 0;
dbReading = false;
dbWriting = false;
}
public synchronized int startRead() { /* see next slides */ }
public synchronized int endRead() { /* see next slides */ }
public synchronized void startWrite() { /* see next slides */ }
public synchronized void endWrite() { /* see next slides */ }
private int readerCount;
private boolean dbReading;
private boolean dbWriting;
}