Exercise 1 Semaphores - Chalmers waiting on a semaphore that is signaled only when the condition...

9
1 Lecture 3 Semaphores Exercise 1 What is the minimum? private int counter = 0; private final int rounds = 100000; 2 PPHT09 – Shared Update public process update ((int id = 0; id<2; id++)) { for(int i = 0; i<rounds; i++) counter++; } Exercise 1 What is the minimum? private int counter = 0; private final int rounds = 100000; public process update 3 PPHT09 – Shared Update public process update ((int id = 0; id<2; id++)) { for(int i = 0; i<rounds; i++) { int tmp = counter; tmp = tmp + 1; counter = tmp; } } Semaphores Summary: Last time Shared update problem/critical section Semaphores and locks 4 PPHT09 – Semaphores Today All you need to know about semaphores Semaphore Specification An abstract datatype containing a nonnegative integer accessed by two atomic operations P and V class Semaphore { 5 PPHT09 – Semaphores private int sv; Semaphore(int init): <sv = init> P(s): <await (sv>0) sv = sv –1> V(s): <sv = sv + 1> } Critical Section – Semaphores JR has built in semaphores sem mutex = 1; process CS ((int i=0;i<2;i++)) { while (true) { 6 PPHT09 – Semaphores while (true) { //Non-critical section P(mutex); //Critical Section V(mutex); } }

Transcript of Exercise 1 Semaphores - Chalmers waiting on a semaphore that is signaled only when the condition...

1

Lecture 3

Semaphores

Exercise 1

• What is the minimum?

private int counter = 0;private final int rounds = 100000;

2PPHT09 – Shared Update

public process update((int id = 0; id<2; id++)) {

for(int i = 0; i<rounds; i++)counter++;

}

Exercise 1

• What is the minimum?

private int counter = 0;private final int rounds = 100000;

public process update

3PPHT09 – Shared Update

public process update((int id = 0; id<2; id++)) {

for(int i = 0; i<rounds; i++) {int tmp = counter;tmp = tmp + 1;counter = tmp;

}}

Semaphores

• Summary: Last time◦ Shared update problem/critical section

◦ Semaphores and locks

4PPHT09 – Semaphores

• Today◦ All you need to know about semaphores

Semaphore Specification

• An abstract data‐type containing a non‐negative integer accessed by two atomic operations P and V

class Semaphore {

5PPHT09 – Semaphores

private int sv;

Semaphore(int init): <sv = init>P(s): <await (sv>0) sv = sv –1>V(s): <sv = sv + 1>

}

Critical Section – Semaphores

• JR has built in semaphores

sem mutex = 1;process CS ((int i=0;i<2;i++)) {

while (true) {

6PPHT09 – Semaphores

while (true) {//Non-critical sectionP(mutex);//Critical SectionV(mutex);

}}

2

Critical Section – Semaphores

• Java has a library support◦ java.util.concurrent

Semaphore mutex = new Semaphore(1, true);

public void run() {

7PPHT09 – Semaphores

public void run() {while (true) {

//Non-critical sectionmutex.acquireUninterruptibly();//Critical Sectionmutex.release();

}}

Binary Semaphores and Locks

• A semaphore which only ever takes on the values 0 and 1 is called a binary semaphore

• When a binary semaphore s is used for simple mutex:

P( t )

8PPHT09 – Semaphores

◦ it is also referred to as a lock. • P(s) – “acquiring the lock”

• V(s) – “releasing the lock”

P(mutex);//Critical SectionV(mutex);

Java Built-In Locks

• A lock is created for every object in Java

• To use this lock we employ the keyword synchronized

9PPHT09 – Semaphores

class MutexCounter {private int counter = 0;

public synchronized void increment() {counter++;

}}

The Dining Philosophers

• A bunch (N) of philosophers who spend their time thinking and eating

• Constraints:

10PPHT09 – Semaphores

Constraints:◦ Only N forks (university funding cuts!)

◦ Can’t eat with only one fork

◦ May only take forks from left and right

TDP – General Program

• Write a program which simulates the behaviour

process Philosopher ((int i=0;i<N;i++)) {hil (t ) {

11PPHT09 – Semaphores

while (true) {ThinkAcquire forksEatRelease forks

}}

Purpose

• Classical problem illustrating ◦ Mutex: only one philosopher at a time may have a fork

◦ Conditional synchronisation: may eat only when has two forks

12PPHT09 – Semaphores

has two forks

◦ Livelock

◦ Deadlock 

◦ Indefinite postponement (starvation)

3

First Attempt

process Philosopher ((int i=0;i<N;i++)) {int left = i,

right = (i+1)%N;while (true) {

//ThinkP(f k [l f ])

13PPHT09 – Semaphores

P(forks[left])P(forks[right])//Eat V(forks[left])V(forks[right])

}}

Deadlock Problem

• If all manage to pick up their left‐hand fork at about the same time then a deadlock occurs

• In general deadlock

14PPHT09 – Semaphores

In general deadlock occurs because there is a circular waiting

Solution 1: Break the Symmetry

• Prevention by not allowing the circular waiting to arise

• By making one of the philosophers different we break the cycle

15PPHT09 – Semaphores

process Philosopher ((int i=0;i<N;i++)) {int left, right;if (i==0) { left = 1; right = 0; }else { left = i; right = (i+1)%N; }…

Solution 2: General Semaphore

• If at most N‐1 philosophers are eating then at least one will always have two forks.

sem chairs = N - 1…

P(chairs)P(forks[left])P(forks[right])

16PPHT09 – Semaphores

• Use a general semaphore to represent N‐1 available chairs

P(forks[right])//Eat V(forks[left])V(forks[right])V(chairs)

Analysis

• Starvation with a fair scheduler?◦ Depends on the implementation of semaphores! 

• Blocked queue (FIFO) guarantees fairness

• Other “queue” policy might not

JR FIFO

17PPHT09 – Semaphores

• JR: FIFO

• Java◦ Default constructor: no

◦ Semaphore(int permits, boolean fair)

A Simple Deadlock Prevention Method

• One simple method for guaranteeing deadlock freedom when using locks for resource protection:◦ Assuming that locks are used correctly to provide 

t ll l i t i di id l

18PPHT09 – Semaphores

mutually exclusive access to individual resources a, b, c, …

◦ Fix a (linear) order for resources. Only allowed to possess multiple resources if they are acquired in that order • solution 1 of the dining philosophers

4

Preventing Deadlock

• Another simple method for guaranteeing deadlock freedom◦ Identify the “circular waiting chains”

◦ Don’t allow enough processes to “fill” the chain

19PPHT09 – Semaphores

• solution 2 of the dining philosophers

Producer Consumer

• Producer‐consumer relationships between processes are a very common pattern

• Problem: how do we allow for different speeds of production vs. consumption?

20PPHT09 – Semaphores

Unbounded Buffers

• Producer can work freely

• Consumer must wait for producer

21PPHT09 – Semaphores

Infinite bar

… …

Bounded Buffers

• Producer must wait if buffer is full

• Consumer must wait if buffer is empty

22PPHT09 – Semaphores

Finite buffer

Buffers Using Semaphores

• One‐slot buffer◦ Multiple producer processes

◦ Multiple consumer processes

◦ Semaphores

23PPHT09 – Semaphores

Split Binary Semaphores

• Two reasons to block: ◦ Producers wait for an (the) empty slot to be available

◦ Consumers wait for a filled slot to be available

24PPHT09 – Semaphores

• Initialisation◦ One empty slot

◦ Zero full slots

• Invariant◦ empty+full<=1

sem empty = 1;sem full = 0;

Data buf;

Shared

5

One-Slot Buffer

process P(1...M) {while(true){

process C(1...N) {Data myData

sem empty = 1, full = 0;Data buf = null;

25PPHT09 – Semaphores

while(true){//Produce dataP(empty);buf = data;V(full);

}}

Data myDatawhile(true){

P(full);myData = buf;V(empty);//Consume myMata

}}

General N-slot Buffer

Producers add to front

26PPHT09 – Semaphores

Consumers take from rear end

General Semaphore

• Counting resources

• Initialisation◦ S empty slots

◦ Zero full slots

sem empty = S;sem full = 0;

Shared

27PPHT09 – Semaphores

• Invariant◦ empty+full<=S

Data buf[S];

int front = 0,rear = 0;

process Producer {while(true){

//Produce dataP(empty)

General N-slot Buffer

• Single producer

28PPHT09 – Semaphores

P(empty);buf[front] = data;front = (front+1)%S;V(full);

}}

• Multiple Producers?

General N-slot Buffer

• Multiple producers

sem mutexP = 1;process Producer((int i=1;i<M;i++)) {

while(true){//Produce data

29PPHT09 – Semaphores

//Produce dataP(empty);P(mutexP);buf[front] = data;front = (front+1)%S;V(mutexP);V(full);

}}

General N-slot Buffer

• Multiple consumerssem mutexC = 1;process Consumer((int i=1;i<N;i++)) {

Data myData;while(true){

30PPHT09 – Semaphores

P(full);P(mutexC);myData = buf[rear];rear = (rear+1)%S;V(mutexC);V(empty);//Consume myData

}}

6

Buffer as ADT

• Encapsulate the synchronisation together with data in an abstract data type

public class Buffer<E> {...

31PPHT09 – Semaphores

public void put(E e) {P(empty);P(mutexP);buf[front] = e;front = (front+1)%S;V(mutexP);V(full);

}}

Buffer as ADT – Usage

Buffer<Data> = new Buffer<Data>(S);

process Producer((int i=1;i<M;i++)) {while(true){

//Produce data

32PPHT09 – Semaphores

buf.put(data);}}process Consumer((int i=1;i<N;i++)) {

while(true){Data myData = buf.take(data);//Consume myData

}}

Preparing for Blocking

• A call to P(s)may involve blocking for a long time◦ A process might need to take precautions before waiting (e.g. set controlled device in safe state)

P bl P i il k l

33PPHT09 – Semaphores

◦ Problem: Precautions unnecessarily taken also when no waiting occurs

//now need to acquire stake_precautions();P(s)

One More Semaphore Operation

• java.util.concurrent.Semaphore has more operations. In particular◦ tryAcquire()

• A non‐blocking operation that acquires the semaphore (and returns true) if that is possible at time of

34PPHT09 – Semaphores

(and returns true) if that is possible at time of invocation. Otherwise, returns false (without acquiring the semaphore).

• Ignores fairness setting!

◦ tryAcquire(0, TimeUnit.SECONDS)• Try to acquire the semaphore while possibly waiting 0 seconds

• Fair equivalent

Stopping a Process – Java

• Semaphore

Semaphore terminate = new Semaphore(0);

public void run() {hil (! i A i ())

35PPHT09 – Semaphores

while (!terminate.tryAcquire())//Do some work here

}

public void shutdown() {terminate.release();

}

Stopping a Process – Java

• One time flag◦ Only one update per program run

volatile boolean terminate = false;

36PPHT09 – Semaphores

public void run() {while (!terminate)

//Do some work here}

public void shutdown() {terminate = true;

}

7

JR – tryAcquire

• JR does not have a direct equivalent

• But JR semaphores are not really semaphores◦ They are special channels

37PPHT09 – Semaphores

y p

• Alternative constructs in JR exist

Assignment 1: Trainspotting

• Write a train controller◦ Independent movement of trains

◦ No crash• sychronised using semaphores

38PPHT09 – Semaphores

Assignment 1

• Interface package TSim◦ Available on all student machines (Linux)

◦ Downloadable

• Special command 2

39PPHT09 – Semaphores

◦ Available on all student machines (Linux)

• The track is fixed◦ But you need to provide sensors

◦ Find the critical sections

• Test, test, test, or prove correctness

Readers/Writers Problem

• Another classic synchronisation problem

• Two kinds of processes share access to a “database”◦ Readers examine the contents

40PPHT09 – Semaphores

◦ Multiple readers allowed concurrently

◦ Writers examine and modify

◦ A writer must have mutex

• Invariant◦ (nr==0 ∨ nw==0) ∧ nw<=1

R/W – Coarse-grained Solution

process R((int i=0;i++;i<M)) {while(true){

<await (nw==0) nr++;>//read database<nr--;>

}}

41PPHT09 – Semaphores

}}

process W((int i=0;i++;i<N)) {while(true){

<await (nr==0 && nw==0) nw++;>//write database<nw--;>

}}

R/W – Passing The Baton

• Split binary semaphore◦ r – for await in readers

◦ w – for await in writers

◦ e – for controlling entry into the “protocol”

42PPHT09 – Semaphores

◦ r+w+e == 1◦ Initially e == 1

• Counters for waiting processes◦ dr – await in readers

◦ dw – await in writers

8

R/W – Passing The Baton

process R((int i=0;i++;i<M)) {while(true){

//<await (nw==0) nr++;>P(e);if (nw>0) { dr++; V(e); P(r); }nr++;

43PPHT09 – Semaphores

nr ;Signal();//read database//<nr--;>P(e);nr--;Signal();

}}

R/W – Passing The Baton

process W((int i=0;i++;i<N)) {while(true){

//<await (nr==0 && nw==0) nw++;>P(e);if (nr>0 || nw>0) { dw++; V(e); P(w); }nw++;

44PPHT09 – Semaphores

nw ;Signal();//write database//<nw--;>P(e);nw--;Signal();

}}

R/W – Passing The Baton

public void Signal() {if (nw==0 && dr>0) {

dr--;V(r);

} else if (nr==0 && nw==0 && dw>0) {

45PPHT09 – Semaphores

} else if (nr==0 && nw==0 && dw>0) {dw--;V(w);

} elseV(e);

R/W – Correctness

• Split binary semaphore◦ Every execution path starts with P and ends with V

◦ mutual exclusion in‐between

• Await guards are guaranteed

46PPHT09 – Semaphores

• Await guards are guaranteed◦ Either true when checked with if‐statement,◦ Or waiting on a semaphore that is signaled only when the condition becomes true

• Invariant◦ Initially true◦ True just before every V

Passing The Baton

• General technique◦ Implements any await statement

• Flexible scheduling policies◦ Readers preference as shown,

47PPHT09 – Semaphores

◦ But the baton can be passed in different ways• New readers are delayed if a writer is waiting

• A delayed reader is awakened only if no writer is currently waiting

• Or use additional parameters to fine‐tune scheduling

Summary – Semaphores

• Good news◦ Simple, efficient, expressive

• Passing the Baton – any await statement

• Bad news

48PPHT09 – Semaphores

◦ Low level, unstructured • omit a V: deadlock

• omit a P: failure of mutex

◦ Synchronisation code not linked to the data• Synchronisation code can be accessed anywere,

• but good programming style helps!

9

Next Time

• Reasoning about concurrent programs◦ Specifying what it means for a concurrent program to behave correctly

◦ Proving that a concurrent program is correct

◦ Testing

49PPHT09 – Semaphores