Concurrent Programming
Shared Memory – Passing the baton – Monitors
Ver´onica Gaspes
www.hh.se/staff/vero
CERES, November 2, 2007
Outline
1 Recap
2 Readers & Writers
Readers & writers (mutual exclusion) Readers & writers (conditions)
A programming technique: Passing the baton
3 Monitors
Monitors in the real world ... Syntax and Semantics Java
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify.
The processesmight need to use some of the variables in mutual exclusion,
wait for the variables to have values satisfying some condition.
Distributed
The processes build one program by sharing some communication mechanism
a mailbox or a telephone line
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify. The processesmight need to
use some of the variables in mutual exclusion,
wait for the variables to have values satisfying some condition.
Distributed
The processes build one program by sharing some communication mechanism
amailboxor atelephone line
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify.
The processesmight need to
use some of the variables in mutual exclusion,
wait for the variables to have values satisfying some condition.
Distributed
The processes build one program by sharing some communication mechanism
amailboxor atelephone line
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify.
The processesmight need to
use some of the variables in
mutual exclusion,
wait for the variables to have values satisfying some condition.
Distributed
The processes build one program by sharing some communication mechanism
amailboxor atelephone line
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify.
The processesmight need to
use some of the variables in
mutual exclusion,
wait for the variables to have
values satisfying some
condition.
Distributed
The processes build one program by sharing some communication mechanism
amailboxor atelephone line
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify.
The processesmight need to
use some of the variables in
mutual exclusion,
wait for the variables to have
values satisfying some
condition.
Distributed
The processes build one program
by sharing some communication
mechanism amailboxor atelephone line
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify.
The processesmight need to
use some of the variables in
mutual exclusion,
wait for the variables to have
values satisfying some
condition.
Distributed
The processes build one program
by sharing some communication
mechanism
amailboxor
Concurrent programming
Programs with many parts(processes, threads) that could be
executed at the same time!
Shared memory
The processes build one program by using some shared variables that they all can read and modify.
The processesmight need to
use some of the variables in
mutual exclusion,
wait for the variables to have
values satisfying some
condition.
Distributed
The processes build one program
by sharing some communication
mechanism
amailboxor atelephone line
Processes in MPD
resource A # specification part body A() process a[i = 1 to 10]{...} process b{...} ... endThe partsa[1], . . . , a[10],band
the rest of the instructions in the bodyare executed concurrently.
resource A # specification part body A() ... co p() // q() oc ... co [i = 1 to 10] {r(i)} oc end
p,qandr(i) are ordinary functions.
Processes in MPD
resource A # specification part body A() process a[i = 1 to 10]{...} process b{...} ... endThe partsa[1], . . . , a[10],band
the rest of the instructions in the bodyare executed concurrently.
resource A # specification part body A() ... co p() // q() oc ... co [i = 1 to 10] {r(i)} oc end
p,qandr(i) are ordinary functions.
Processes in MPD
resource A # specification part body A() process a[i = 1 to 10]{...} process b{...} ... endThe partsa[1], . . . , a[10],band
the rest of the instructions in the
bodyare executed concurrently.
resource A # specification part body A() ... co p() // q() oc ... co [i = 1 to 10] {r(i)} oc end
p,qandr(i) are ordinary functions.
Processes in MPD
resource A # specification part body A() process a[i = 1 to 10]{...} process b{...} ... endThe partsa[1], . . . , a[10],band
the rest of the instructions in the
bodyare executed concurrently.
resource A # specification part body A() ... co p() // q() oc ... co [i = 1 to 10] {r(i)} oc end
p,qandr(i) are ordinary functions.
Processes in MPD
resource A # specification part body A() process a[i = 1 to 10]{...} process b{...} ... endThe partsa[1], . . . , a[10],band
the rest of the instructions in the
bodyare executed concurrently.
resource A # specification part body A() ... co p() // q() oc ... co [i = 1 to 10] {r(i)} oc end
p,qandr(i) are ordinary
Threads in Java
class A{
...
public static void main(String[] cmndLn){
... new T1().start(); new T2().start(); ... } }
class T1 implements Runnable { public void run(){...}
}
class T2 extends Thread { public void run(){...} }
Threads in Java
class A{
...
public static void main(String[] cmndLn){
... new T1().start(); new T2().start(); ... } }
class T1 implements Runnable { public void run(){...}
}
class T2 extends Thread { public void run(){...} }
Threads in Java
class A{
...
public static void main(String[] cmndLn){
... new T1().start(); new T2().start(); ... } }
class T1 implements Runnable { public void run(){...}
}
class T2 extends Thread { public void run(){...} }
Threads in Java
class A{
...
public static void main(String[] cmndLn){
... new T1().start(); new T2().start(); ... } }
class T1 implements Runnable { public void run(){...}
}
class T2 extends Thread { public void run(){...} }
Semaphores
Languages that provide ways to describeprocessesprovide also
ways tosynchronizethe processes.
One such mechanism for shared memory issemaphores.
Mutual Exclusion
Processes share a semaphore, say mutex
with initial value 1
follow the protocol P(mutex)
#exclusive V(mutex)
Wait on conditions
Identify the conditions, possibly introduce variables to express them,
follow the technique called
passing the baton! It is important to follow working techniques because it is impossible to debug concurrent programs!
Semaphores
Languages that provide ways to describeprocessesprovide also
ways tosynchronizethe processes.
One such mechanism for shared memory issemaphores.
Mutual Exclusion
Processes share a semaphore, say mutex
with initial value 1
follow the protocol
P(mutex) #exclusive V(mutex)
Wait on conditions
Identify the conditions, possibly introduce variables to express them,
follow the technique called
passing the baton! It is important to follow working techniques because it is impossible to debug concurrent programs!
Semaphores
Languages that provide ways to describeprocessesprovide also
ways tosynchronizethe processes.
One such mechanism for shared memory issemaphores.
Mutual Exclusion
Processes share a semaphore, say mutex
with initial value 1
follow the protocol
P(mutex) #exclusive V(mutex)
Wait on conditions
Identify the conditions, possibly introduce variables to express them,
follow the technique called
passing the baton! It is important to follow working techniques because it is impossible to debug concurrent programs!
Readers & Writers - why?
A problem withselectivemutual exclusion (as opposed to critical
sections!)
One solution based on mutual exclusion synchronization that has fairness problems : writers might starve.
Another solution based on condition synchronization that illustrates a general programming technique: passing the baton.
Readers & Writers - why?
A problem withselectivemutual exclusion (as opposed to critical
sections!)
One solution based on mutual exclusion synchronization that has
fairness problems : writers might starve.
Another solution based on condition synchronization that illustrates a general programming technique: passing the baton.
Readers & Writers - why?
A problem withselectivemutual exclusion (as opposed to critical
sections!)
One solution based on mutual exclusion synchronization that has
fairness problems : writers might starve.
Another solution based on condition synchronization that
illustrates a general programming technique: passing the baton.
Readers & Writers - why?
A problem withselectivemutual exclusion (as opposed to critical
sections!)
One solution based on mutual exclusion synchronization that has
fairness problems : writers might starve.
Another solution based on condition synchronization that
illustrates a general programming technique: passing the baton.
Readers & Writers - problem statement
Two kinds of processes (Readersand Writers) share a
database.
Readers execute transactions thatexamine database records. Writersexecute transactions that both examineand update database records.
The database is consistent initially and transactions, if performed in isolation, preserve consistency.
A writer must haveexclusive access to the database. Assuming no writeris using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement
Two kinds of processes (Readersand Writers) share a
database.
Readers execute transactions thatexamine database records.
Writersexecute transactions that both examineand update database records.
The database is consistent initially and transactions, if performed in isolation, preserve consistency.
A writer must haveexclusive access to the database. Assuming no writeris using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement
Two kinds of processes (Readersand Writers) share a
database.
Readers execute transactions thatexamine database records.
Writersexecute transactions that both examineand update
database records.
The database is consistent initially and transactions, if performed in isolation, preserve consistency.
A writer must haveexclusive access to the database. Assuming no writeris using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement
Two kinds of processes (Readersand Writers) share a
database.
Readers execute transactions thatexamine database records.
Writersexecute transactions that both examineand update
database records.
The database is consistent initially and transactions, if performed in isolation, preserve consistency.
A writer must haveexclusive access to the database. Assuming no writeris using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement
Two kinds of processes (Readersand Writers) share a
database.
Readers execute transactions thatexamine database records.
Writersexecute transactions that both examineand update
database records.
The database is consistent initially and transactions, if performed in isolation, preserve consistency.
A writer must haveexclusive access to the database.
Assuming no writeris using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement
Two kinds of processes (Readersand Writers) share a
database.
Readers execute transactions thatexamine database records.
Writersexecute transactions that both examineand update
database records.
The database is consistent initially and transactions, if performed in isolation, preserve consistency.
A writer must haveexclusive access to the database.
Assuming no writeris using the database, any number of
R&W - mutual exclusion
Firstoverconstrainthe solution:
treat it as critical sections.
Then relax the constraints so that readers can execute concurrently: Only thefirst reader has tograb the lockto the database; only the
last readerhas torelease the lock.
We need a shared variable to countthe number of readers accessing the database!
sem rw = 1 process Reader[i = 1 to M]{ while(true){ P(rw) # read! V(rw) } } process Writer[j = 1 to N]{ while(true){ P(rw) # write! V(rw) } }
R&W - mutual exclusion
Firstoverconstrainthe solution:
treat it as critical sections.
Then relax the constraints so that readers can execute concurrently: Only thefirst reader has tograb the lockto the database; only the
last readerhas torelease the lock.
We need a shared variable to countthe number of readers accessing the database!
sem rw = 1 process Reader[i = 1 to M]{ while(true){ P(rw) # read! V(rw) } } process Writer[j = 1 to N]{ while(true){ P(rw) # write! V(rw) } }
R&W - mutual exclusion
Firstoverconstrainthe solution:
treat it as critical sections.
Then relax the constraints so that readers can execute concurrently:
Only thefirst reader has tograb
the lockto the database; only the
last readerhas torelease the lock.
We need a shared variable to countthe number of readers accessing the database!
sem rw = 1 process Reader[i = 1 to M]{ while(true){ P(rw) # read! V(rw) } } process Writer[j = 1 to N]{ while(true){ P(rw) # write! V(rw) } }
R&W - mutual exclusion
Firstoverconstrainthe solution:
treat it as critical sections.
Then relax the constraints so that readers can execute concurrently:
Only thefirst reader has tograb
the lockto the database; only the
last readerhas torelease the lock. We need a shared variable to
countthe number of readers
accessing the database!
sem rw = 1 process Reader[i = 1 to M]{ while(true){ P(rw) # read! V(rw) } } process Writer[j = 1 to N]{ while(true){ P(rw) # write! V(rw) } }
R&W - mutual exclusion
sem rw = 1 # lock to the database
sem mutexR = 1 # lock to the counter of readers
int nr = 0 # counter of readers
process Reader[i = 1 to m] while(true) P(mutexR) nr = nr+1 if(nr == 1){P(rw)} V(mutexR) # read! P(mutexR) nr = nr-1 if (nr == 0){V(rw)} V(mutexR) process Writer[j = 1 to n] while(true) P(rw) # write! V(rw)
Once a reader gets access, writers might starve: as long as new readers arrive writers have to wait!
R&W - mutual exclusion
sem rw = 1 # lock to the database
sem mutexR = 1 # lock to the counter of readers
int nr = 0 # counter of readers
process Reader[i = 1 to m] while(true) P(mutexR) nr = nr+1 if(nr == 1){P(rw)} V(mutexR) # read! P(mutexR) nr = nr-1 if (nr == 0){V(rw)} V(mutexR) process Writer[j = 1 to n] while(true) P(rw) # write! V(rw)
Once a reader gets access, writers might starve: as long as new readers arrive writers have to wait!
R&W - mutual exclusion
sem rw = 1 # lock to the database
sem mutexR = 1 # lock to the counter of readers
int nr = 0 # counter of readers
process Reader[i = 1 to m] while(true) P(mutexR) nr = nr+1 if(nr == 1){P(rw)} V(mutexR) # read! P(mutexR) nr = nr-1 if (nr == 0){V(rw)} V(mutexR) process Writer[j = 1 to n] while(true) P(rw) # write! V(rw)
Once a reader gets access, writers might starve: as long as new readers arrive writers have to wait!
R&W - mutual exclusion
sem rw = 1 # lock to the database
sem mutexR = 1 # lock to the counter of readers
int nr = 0 # counter of readers
process Reader[i = 1 to m] while(true) P(mutexR) nr = nr+1 if(nr == 1){P(rw)} V(mutexR) # read! P(mutexR) nr = nr-1 if (nr == 0){V(rw)} V(mutexR) process Writer[j = 1 to n] while(true) P(rw) # write! V(rw)
Once a reader gets access, writers might starve: as long as new readers arrive writers have to wait!
R&W - conditions
Countthe number of readers and the number of writers trying to
access the database andconstrain the valuesof the counters.
Letnr andnw be nonnegative integers recording the number of readers and the number of writers accessing the database. The following condition shouldbe true for all states:
Good States
R&W - conditions
Countthe number of readers and the number of writers trying to
access the database andconstrain the valuesof the counters.
Letnr andnw be nonnegative integers recording the number of
readers and the number of writers accessing the database. The
following condition shouldbe true for all states:
Good States
R&W - conditions
Countthe number of readers and the number of writers trying to
access the database andconstrain the valuesof the counters.
Letnr andnw be nonnegative integers recording the number of
readers and the number of writers accessing the database. The
following condition shouldbe true for all states:
Good States
A skeleton
int nr = 0, nw = 0
process Reader[i = 1 to m] while(true)
#ATOMIC: await (nw==0) then nr = nr+1
# read!
#ATOMIC: nr = nr-1
process Writer[j = 1 to n] while(true)
#ATOMIC: await (nr==0 and nw==0) then nw = nw+1
# write!
Implementing waiting on conditions
Passing the baton
When a process is executing within a critical section, think of it as holding a baton that means Permission to execute. When a process has done what it was waiting to do it passes the baton toone other process:
If some process is waiting for a condition that isnow true, the baton is passed to one such process.
When no process is waiting on a condition that is true, the baton is passed to the next process that tries to enter the critical section.
Implementing waiting on conditions
Passing the baton
When a process is executing within a critical section, think of
it as holding a baton that means Permission to execute.
When a process has done what it was waiting to do it passes the baton toone other process:
If some process is waiting for a condition that isnow true, the baton is passed to one such process.
When no process is waiting on a condition that is true, the baton is passed to the next process that tries to enter the critical section.
Implementing waiting on conditions
Passing the baton
When a process is executing within a critical section, think of
it as holding a baton that means Permission to execute.
When a process has done what it was waiting to do it passes
the baton toone other process:
If some process is waiting for a condition that isnow true, the baton is passed to one such process.
When no process is waiting on a condition that is true, the baton is passed to the next process that tries to enter the critical section.
Implementing waiting on conditions
Passing the baton
When a process is executing within a critical section, think of
it as holding a baton that means Permission to execute.
When a process has done what it was waiting to do it passes
the baton toone other process:
If some process is waiting for a condition that isnow true, the baton is passed to one such process.
When no process is waiting on a condition that is true, the baton is passed to the next process that tries to enter the critical section.
Implementing waiting on conditions
Passing the baton
When a process is executing within a critical section, think of
it as holding a baton that means Permission to execute.
When a process has done what it was waiting to do it passes
the baton toone other process:
If some process is waiting for a condition that isnow true, the baton is passed to one such process.
When no process is waiting on a condition that is true, the baton is passed to the next process that tries to enter the critical section.
Implementing atomic waiting on conditions
Use a semaphore to control entry into each atomic statement:
sem e = 1
Associate a semaphore with each condition and count the number of delayed processes on each semaphore:
sem r = 0; int dr = 0 sem w = 0; int dw = 0
Implementing atomic waiting on conditions
await (nw==0) then nr = nr+1
P(e)
if (nw > 0){dr=dr+1; V(e); P(r)} nr = nr+1
Implementing atomic waiting on conditions
await (nw==0) then nr = nr+1
P(e)
if (nw > 0){dr=dr+1; V(e); P(r)} nr = nr+1
Implementing atomic waiting on conditions
nr = nr-1
P(e) nr = nr-1
Implementing atomic waiting on conditions
nr = nr-1
P(e) nr = nr-1
Implementing atomic waiting on conditions
await (nr == 0 and nw==0) then nw = nw+1
P(e)
if (nr > 0 or nw > 0){dw=dw+1; V(e); P(w)} nw = nw+1
Implementing atomic waiting on conditions
await (nr == 0 and nw==0) then nw = nw+1
P(e)
if (nr > 0 or nw > 0){dw=dw+1; V(e); P(w)} nw = nw+1
Implementing atomic waiting on conditions
nw = nw-1 P(e) nw = nw-1 if(dr>0) {dr=dr-1;V(r)} elseif(dw>0){dw=dw-1;V(w)} else {V(e)}Implementing atomic waiting on conditions
nw = nw-1 P(e) nw = nw-1 if(dr>0) {dr=dr-1;V(r)} elseif(dw>0){dw=dw-1;V(w)} else {V(e)}An
Abstract Data Type
. . .
Example
class Counter{
private int x = 0;
public void inc(){ int tmp = x; Support.nap(10); tmp++; Support.nap(10); x = tmp; } } Example resource Counter op inc() body Counter() int x = 0 proc inc(){ int tmp = x nap(10);tmp++;nap(10) x = tmp } end
An
Abstract Data Type
. . .
Example
class Counter{
private int x = 0;
public void inc(){ int tmp = x; Support.nap(10); tmp++; Support.nap(10); x = tmp; } } Example resource Counter op inc() body Counter() int x = 0 proc inc(){ int tmp = x nap(10);tmp++;nap(10) x = tmp } end
An
Abstract Data Type
. . .
Example
class Counter{
private int x = 0;
public void inc(){ int tmp = x; Support.nap(10); tmp++; Support.nap(10); x = tmp; } } Example resource Counter op inc() body Counter() int x = 0 proc inc(){ int tmp = x nap(10);tmp++;nap(10) x = tmp } end
. . . that supports
Mutual Exclusion
Exampleimport java.util.concurrency.locks.*;
class Counter{
private final Lock lock = new ReentrantLock();
private int x = 0;
public void inc(){ lock.lock(); try{ int tmp = x; Support.nap(10); tmp++; Support.nap(10); x = tmp; }finally{lock.unlock();} }
. . . that supports
Mutual Exclusion
Example resource Counter op inc() body Counter() sem mutex = 1 int x = 0 proc inc(){ P(mutex) int tmp = x nap(10);tmp++;nap(10) x = tmp V(mutex) } endWhat does this mean?
The abstract data type can be shared by many threads while preserving the integrity of the representation! Only one thread at a time is allowed to be using themonitor. All other threads are blocked until they can be given permission to enter.
Example
cap Counter c = create Counter()
process Turnstile[p = 1 to nrOfT]{
while(true){ c.inc()
nap(int(floor(random()*100))) }
What does this mean?
The abstract data type can be shared by many threads while preserving the integrity of the representation!
Only one thread at a time is allowed to be using themonitor. All other threads are blocked until they can be given permission to enter.
Example
cap Counter c = create Counter()
process Turnstile[p = 1 to nrOfT]{
while(true){ c.inc()
nap(int(floor(random()*100))) }
What does this mean?
The abstract data type can be shared by many threads while preserving the integrity of the representation! Only one thread at a time is allowed to be
using themonitor.
All other threads are blocked until they can be given permission to enter.
Example
cap Counter c = create Counter()
process Turnstile[p = 1 to nrOfT]{
while(true){ c.inc()
nap(int(floor(random()*100))) }
What does this mean?
The abstract data type can be shared by many threads while preserving the integrity of the representation! Only one thread at a time is allowed to be
using themonitor.
All other threads are blocked until they can be given permission to enter.
Example
cap Counter c = create Counter()
process Turnstile[p = 1 to nrOfT]{
while(true){ c.inc()
nap(int(floor(random()*100))) }
What does this mean?
The abstract data type can be shared by many threads while preserving the integrity of the representation! Only one thread at a time is allowed to be
using themonitor.
All other threads are blocked until they can be given permission to enter.
Example
cap Counter c = create Counter()
process Turnstile[p = 1 to nrOfT]{
while(true){ c.inc()
nap(int(floor(random()*100))) }
And support for
Condition Synchronization
With more elaborateabstract data types, threads might need to be
blocked until some conditionholds for the abstract datatype.
Example
In thebounded bufferthat is shared by producerthreads and
consumerthreads:
Producers might have towait untilthebuffer is not full. Consumers might have towait untilthebuffer is not empty. Languages supporting monitors provide atype forcondition variables. We first discuss their purpose and expected operations. Then we look at Java. Then we do an example.
And support for
Condition Synchronization
With more elaborateabstract data types, threads might need to be
blocked until some conditionholds for the abstract datatype.
Example
In thebounded bufferthat is shared by producerthreads and
consumerthreads:
Producers might have towait untilthebuffer is not full.
Consumers might have towait untilthebuffer is not empty.
Languages supporting monitors provide atype forcondition variables. We first discuss their purpose and expected operations. Then we look at Java. Then we do an example.
And support for
Condition Synchronization
With more elaborateabstract data types, threads might need to be
blocked until some conditionholds for the abstract datatype.
Example
In thebounded bufferthat is shared by producerthreads and
consumerthreads:
Producers might have towait untilthebuffer is not full.
Consumers might have towait untilthebuffer is not empty.
Languages supporting monitors provide atype forcondition variables. We first discuss their purpose and expected operations. Then we look at Java. Then we do an example.
And support for
Condition Synchronization
With more elaborateabstract data types, threads might need to be
blocked until some conditionholds for the abstract datatype.
Example
In thebounded bufferthat is shared by producerthreads and
consumerthreads:
Producers might have towait untilthebuffer is not full.
Consumers might have towait untilthebuffer is not empty.
Languages supporting monitors provide atype forcondition variables. We first discuss their purpose and expected operations. Then we look at Java. Then we do an example.
And support for
Condition Synchronization
With more elaborateabstract data types, threads might need to be
blocked until some conditionholds for the abstract datatype.
Example
In thebounded bufferthat is shared by producerthreads and
consumerthreads:
Producers might have towait untilthebuffer is not full.
Consumers might have towait untilthebuffer is not empty.
Languages supporting monitors provide atype forcondition
variables. We first discuss their purpose and expected operations. Then we look at Java. Then we do an example.
Monitors offer
Condition Variables
Used to
Delay a process that cannot safely continue executing until the monitor’s state satisfies some property.
Awakena delayed process when the property holds. How?
1 Inside a monitor declare a variable of the type for condition variables cond cv.
2 A processblockson a condition variable by executing
wait(cv).
3 Processes that are blocked on condition variablesget awaken by signal(cv).
Monitors offer
Condition Variables
Used to
Delay a process that cannot safely continue executing until the monitor’s state satisfies some property.
Awakena delayed process when the property holds. How?
1 Inside a monitor declare a variable of the type for condition variables cond cv.
2 A processblockson a condition variable by executing
wait(cv).
3 Processes that are blocked on condition variablesget awaken by signal(cv).
Monitors offer
Condition Variables
Used to
Delay a process that cannot safely continue executing until the monitor’s state satisfies some property.
Awakena delayed process when the property holds.
How?
1 Inside a monitor declare a variable of the type for condition variables cond cv.
2 A processblockson a condition variable by executing
wait(cv).
3 Processes that are blocked on condition variablesget awaken by signal(cv).
Monitors offer
Condition Variables
Used to
Delay a process that cannot safely continue executing until the monitor’s state satisfies some property.
Awakena delayed process when the property holds.
How?
1 Inside a monitor declare a variable of the type for condition variables cond cv.
2 A processblockson a condition variable by executing
wait(cv).
3 Processes that are blocked on condition variablesget awaken by signal(cv).
Monitors offer
Condition Variables
Used to
Delay a process that cannot safely continue executing until the monitor’s state satisfies some property.
Awakena delayed process when the property holds.
How?
1 Inside a monitor declare a variable of the type for condition
variables cond cv.
2 A processblockson a condition variable by executing
wait(cv).
3 Processes that are blocked on condition variablesget awaken by signal(cv).
Monitors offer
Condition Variables
Used to
Delay a process that cannot safely continue executing until the monitor’s state satisfies some property.
Awakena delayed process when the property holds.
How?
1 Inside a monitor declare a variable of the type for condition
variables cond cv.
2 A processblockson a condition variable by executing
wait(cv).
3 Processes that are blocked on condition variablesget awaken by signal(cv).
Monitors offer
Condition Variables
Used to
Delay a process that cannot safely continue executing until the monitor’s state satisfies some property.
Awakena delayed process when the property holds.
How?
1 Inside a monitor declare a variable of the type for condition
variables cond cv.
2 A processblockson a condition variable by executing
wait(cv).
3 Processes that are blocked on condition variablesget awaken
Semantics
Values
Thevalueof a condition variable is a queue of delayed processes.
Wait
The process that executeswait(cv) gets delayed at the rear of the queue forcv. It relinquishes exclusive access to the monitor. Signal
Execution of signal(cv) examinescv’s queue. If it is empty it has no effect. If there are delayed porcesses, it awakens the process at the front of the queue.
Semantics
Values
Thevalueof a condition variable is a queue of delayed processes.
Wait
The process that executeswait(cv) gets delayed at the rear of the queue forcv. It relinquishes exclusive access to the monitor. Signal
Execution of signal(cv) examinescv’s queue. If it is empty it has no effect. If there are delayed porcesses, it awakens the process at the front of the queue.
Semantics
Values
Thevalueof a condition variable is a queue of delayed processes.
Wait
The process that executeswait(cv) gets delayed at the rear of
the queue forcv. It relinquishes exclusive access to the monitor.
Signal
Execution of signal(cv) examinescv’s queue. If it is empty it has no effect. If there are delayed porcesses, it awakens the process at the front of the queue.
Semantics
Values
Thevalueof a condition variable is a queue of delayed processes.
Wait
The process that executeswait(cv) gets delayed at the rear of
the queue forcv. It relinquishes exclusive access to the monitor.
Signal
Execution of signal(cv) examinescv’s queue. If it is empty it
has no effect. If there are delayed porcesses, it awakens the process
Semantics -
signaling disciplines
Who will get to run when a process doessignal(cv)? The
signaling process? The newly awaken process?
Signal and Continue
The signaler continues, the signaledprocess executes at some later time.
Signal and Wait
The signaler waits until some other time and the signaled process executes now.
Signal and Continueis implemented in Unix, Java and PThreads. It is compatible with priority scheduling, programs are easier to understand.
Semantics -
signaling disciplines
Who will get to run when a process doessignal(cv)? The
signaling process? The newly awaken process?
Signal and Continue
The signaler continues, the signaledprocess executes at some later
time.
Signal and Wait
The signaler waits until some other time and the signaled process executes now.
Signal and Continueis implemented in Unix, Java and PThreads. It is compatible with priority scheduling, programs are easier to understand.
Semantics -
signaling disciplines
Who will get to run when a process doessignal(cv)? The
signaling process? The newly awaken process?
Signal and Continue
The signaler continues, the signaledprocess executes at some later
time.
Signal and Wait
The signaler waits until some other time and the signaled process
executes now.
Signal and Continueis implemented in Unix, Java and PThreads. It is compatible with priority scheduling, programs are easier to understand.
Semantics -
signaling disciplines
Who will get to run when a process doessignal(cv)? The
signaling process? The newly awaken process?
Signal and Continue
The signaler continues, the signaledprocess executes at some later
time.
Signal and Wait
The signaler waits until some other time and the signaled process
executes now.
Signal and Continueis implemented in Unix, Java and PThreads. It is compatible with priority scheduling, programs are easier to understand.
java.util.concurrent.locks
Monitors (locks and condition types) are provided in the package
java.util.concurrent.locks
The interfaceCondition
Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to ”wait”) until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread.
java.util.concurrent.locks
Monitors (locks and condition types) are provided in the package
java.util.concurrent.locks
The interfaceCondition
Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to ”wait”) until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread.
java.util.concurrent.locks
ACondition instance is intrinsically bound to a lock. To obtain a
Conditioninstance for a particular Lock instance use its
newCondition()method.
Example
class BoundedBuffer<T>{
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
private int count = 0;
private int n;
private T[] buf;
private int front = 0;
private int rear = 0; ...}
java.util.concurrent.locks
ACondition instance is intrinsically bound to a lock. To obtain a
Conditioninstance for a particular Lock instance use its
newCondition()method.
Example
class BoundedBuffer<T>{
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
private int count = 0;
private int n;
private T[] buf;
private int front = 0;
private int rear = 0; ...}
Using
Condition
Example
public void deposit(T item){ lock.lock();
try{
while(count == n) notFull.await(); buf[rear] = item;
rear = inc(rear); count++;
notEmpty.signal();
}catch(InterruptedException e){
System.out.println(e.getMessage());}
finally{ lock.unlock(); } }
Using
Condition
Examplepublic T fetch(){ lock.lock();
try{
while(count == 0) notEmpty.await(); T result = buf[front];
front = inc(front); count--;
notFull.signal();
return result;
}catch(InterruptedException e){
System.out.println(e.getMessage());return null;}
finally{ lock.unlock(); } }
Scheduling readers and writers
The scheduler has 2 roles:
Schedule requests. Ensure that no writer is using the database when readers are using it. Ensure that only one writer at a time uses the database.
Scheduling readers and writers
The scheduler has 2 roles:
Schedule requests. Ensure that no writer is using the database when readers are using it. Ensure that only one writer at a time uses the database.
Scheduling readers and writers
The scheduler has 2 roles:
Schedule requests. Ensure that no writer is using the database when readers are using it. Ensure that only one writer at a time uses the database.
Scheduling readers and writers
The scheduler has 2 roles:
Schedule requests. Ensure that no writer is using the database when readers are using it. Ensure that only one writer at a time uses the database.
Scheduling readers and writers
The scheduler has 2 roles:
Schedule requests.
Ensure that no writer is using the database when readers are using it. Ensure that only one writer at a time uses the database.
Scheduling readers and writers
The scheduler has 2 roles:
Schedule requests. Ensure that no writer is using the database when readers are using it.
Ensure that only one writer at a time uses the database.
Scheduling readers and writers
The scheduler has 2 roles:
Schedule requests. Ensure that no writer is using the database when readers are using it. Ensure that only one writer at a time uses the database.
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write 3 Release the
database
Readers have to follow
1 Request permission
to read
2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write 3 Release the
database
Readers have to follow
1 Request permission
to read
2 Read 3 Release the
Scheduling readers and writers
Writers have to follow 1 Request permission
to write 2 Write 3 Release the
database
Readers have to follow 1 Request permission
to read 2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission to write
2 Write 3 Release the
database
Readers have to follow 1 Request permission
to read 2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write 3 Release the
database
Readers have to follow 1 Request permission
to read 2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write
3 Release the database
Readers have to follow 1 Request permission
to read 2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write
3 Release the
database
Readers have to follow 1 Request permission
to read 2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write
3 Release the
database
Readers have to follow
1 Request permission to read
2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write
3 Release the
database
Readers have to follow
1 Request permission
to read
2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write
3 Release the
database
Readers have to follow
1 Request permission
to read
2 Read 3 Release the
Scheduling readers and writers
Writers have to follow
1 Request permission
to write
2 Write
3 Release the
database
Readers have to follow
1 Request permission
to read
2 Read
3 Release the
Organizing the program in Java
import java.util.concurrent.locks.*; class RWScheduler{
public void requestRead()
public void requestWrite()
public void releaseRead()
public void releaseWrite()
Organizing the program in Java
class Reader extends Thread{ private RWScheduler rws; private DB db;
public Reader(int id, RWScheduler rws, DB db){ this.rws = rws;
this.db = db; }
public void run(){ while(true){ rws.requestRead(); db.read(); rws.releaseRead(); } } }
Organizing the program in Java
class Writer extends Thread{ private RWScheduler rws; private DB db;
public Writer(int id, RWScheduler rws, DB db){ this.rws = rws;
this.db = db; }
public void run(){ while(true){ rws.requestWrite(); db.write(...); rws.releaseWrite(); } } }
How do we program the scheduler?
The scheduler has to delay readers and/or writers until they have the right to use the database. For doing so, it counts the number of readers and number of writers using the db.
The scheduler has to wake up readers and/or writers following some policy. For doing so, it counts the number of delayed readers and writers.
How do we program the scheduler?
The scheduler has to delay readers and/or writers until they have the right to use the database. For doing so, it counts the number of readers and number of writers using the db.
The scheduler has to wake up readers and/or writers following some policy. For doing so, it counts the number of delayed readers and writers.
Scheduler code
import java.util.concurrent.locks.*; class RWScheduler{ private int nr = 0; private int nw = 0; private int dr = 0; private int dw = 0;private ReentrantLock lock = new ReentrantLock(); private Condition reader = lock.newCondition(); private Condition writer = lock.newCondition();
Scheduler code —
requestRead
import java.util.concurrent.locks.*; class RWScheduler{
public void requestRead(){
lock.lock(); try{
while(nw > 0) {dr++;reader.await();}
nr++;
if(nr==1){dr=0;reader.signalAll();} }catch(InterruptedException e){}
finally{lock.unlock();} }
Scheduler code —
releaseRead
import java.util.concurrent.locks.*; class RWScheduler{
public void releaseRead(){
lock.lock(); try{
nr--;
if(nr==0 && dw>0){dw--;writer.signal();} }finally{lock.unlock();}
Scheduler code —
requestWrite
import java.util.concurrent.locks.*; class RWScheduler{
public void requestWrite(){
lock.lock(); try{
while(nw > 0 || nr >0) {dw++;writer.await();}
nw++;
}catch(InterruptedException e){} finally{lock.unlock();}
Scheduler code —
releaseWrite
import java.util.concurrent.locks.*; class RWScheduler{
public void releaseWrite(){
lock.lock(); try{
nw--;
if(dr>0){dr--;reader.signal();} else{dw--;writer.signal();} }finally{lock.unlock();}