Concurrent Programming Shared Memory Passing the baton Monitors Verónica Gaspes www.hh.se/staff/vero CERES, November 2, 2007 ceres
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 Readers & Writers revisited
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 processes might 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 processes might 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 processes might 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 processes might 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 processes might 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 processes might 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 processes might 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 processes might 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
Processes in MPD resource A # specification part body A() process a[i = 1 to 10]{... process... end b{... The parts a[1],..., a[10], b and the rest of the instructions in the body are executed concurrently. resource A # specification part body A()... co p() // q() oc... co [i = 1 to 10] {r(i) oc end p, q and r(i) are ordinary functions.
Processes in MPD resource A # specification part body A() process a[i = 1 to 10]{... process... end b{... The parts a[1],..., a[10], b and the rest of the instructions in the body are executed concurrently. resource A # specification part body A()... co p() // q() oc... co [i = 1 to 10] {r(i) oc end p, q and r(i) are ordinary functions.
Processes in MPD resource A # specification part body A() process a[i = 1 to 10]{... process... end b{... The parts a[1],..., a[10], b and the rest of the instructions in the body are executed concurrently. resource A # specification part body A()... co p() // q() oc... co [i = 1 to 10] {r(i) oc end p, q and r(i) are ordinary functions.
Processes in MPD resource A # specification part body A() process a[i = 1 to 10]{... process... end b{... The parts a[1],..., a[10], b and the rest of the instructions in the body are executed concurrently. resource A # specification part body A()... co p() // q() oc... co [i = 1 to 10] {r(i) oc end p, q and r(i) are ordinary functions.
Processes in MPD resource A # specification part body A() process a[i = 1 to 10]{... process... end b{... The parts a[1],..., a[10], b and the rest of the instructions in the body are executed concurrently. resource A # specification part body A()... co p() // q() oc... co [i = 1 to 10] {r(i) oc end p, q and r(i) are ordinary functions.
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 describe processes provide also ways to synchronize the processes. One such mechanism for shared memory is semaphores. 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 describe processes provide also ways to synchronize the processes. One such mechanism for shared memory is semaphores. 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 describe processes provide also ways to synchronize the processes. One such mechanism for shared memory is semaphores. 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 with selective mutual 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. Both solutions use semaphores.
Readers & Writers - why? A problem with selective mutual 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. Both solutions use semaphores.
Readers & Writers - why? A problem with selective mutual 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. Both solutions use semaphores.
Readers & Writers - why? A problem with selective mutual 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. Both solutions use semaphores.
Readers & Writers - problem statement Two kinds of processes (Readers and Writers) share a database. Readers execute transactions that examine database records. Writers execute transactions that both examine and update database records. The database is consistent initially and transactions, if performed in isolation, preserve consistency. A writer must have exclusive access to the database. Assuming no writer is using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement Two kinds of processes (Readers and Writers) share a database. Readers execute transactions that examine database records. Writers execute transactions that both examine and update database records. The database is consistent initially and transactions, if performed in isolation, preserve consistency. A writer must have exclusive access to the database. Assuming no writer is using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement Two kinds of processes (Readers and Writers) share a database. Readers execute transactions that examine database records. Writers execute transactions that both examine and update database records. The database is consistent initially and transactions, if performed in isolation, preserve consistency. A writer must have exclusive access to the database. Assuming no writer is using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement Two kinds of processes (Readers and Writers) share a database. Readers execute transactions that examine database records. Writers execute transactions that both examine and update database records. The database is consistent initially and transactions, if performed in isolation, preserve consistency. A writer must have exclusive access to the database. Assuming no writer is using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement Two kinds of processes (Readers and Writers) share a database. Readers execute transactions that examine database records. Writers execute transactions that both examine and update database records. The database is consistent initially and transactions, if performed in isolation, preserve consistency. A writer must have exclusive access to the database. Assuming no writer is using the database, any number of readers may concurrently execute transactions.
Readers & Writers - problem statement Two kinds of processes (Readers and Writers) share a database. Readers execute transactions that examine database records. Writers execute transactions that both examine and update database records. The database is consistent initially and transactions, if performed in isolation, preserve consistency. A writer must have exclusive access to the database. Assuming no writer is using the database, any number of readers may concurrently execute transactions.
R&W - mutual exclusion First overconstrain the solution: treat it as critical sections. Then relax the constraints so that readers can execute concurrently: Only the first reader has to grab the lock to the database; only the last reader has to release the lock. We need a shared variable to count the 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 First overconstrain the solution: treat it as critical sections. Then relax the constraints so that readers can execute concurrently: Only the first reader has to grab the lock to the database; only the last reader has to release the lock. We need a shared variable to count the 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 First overconstrain the solution: treat it as critical sections. Then relax the constraints so that readers can execute concurrently: Only the first reader has to grab the lock to the database; only the last reader has to release the lock. We need a shared variable to count the 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 First overconstrain the solution: treat it as critical sections. Then relax the constraints so that readers can execute concurrently: Only the first reader has to grab the lock to the database; only the last reader has to release the lock. We need a shared variable to count the 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 Count the number of readers and the number of writers trying to access the database and constrain the values of the counters. Let nr and nw be nonnegative integers recording the number of readers and the number of writers accessing the database. The following condition should be true for all states: Good States (nr == 0 and nw <= 1) or nw == 0
R&W - conditions Count the number of readers and the number of writers trying to access the database and constrain the values of the counters. Let nr and nw be nonnegative integers recording the number of readers and the number of writers accessing the database. The following condition should be true for all states: Good States (nr == 0 and nw <= 1) or nw == 0
R&W - conditions Count the number of readers and the number of writers trying to access the database and constrain the values of the counters. Let nr and nw be nonnegative integers recording the number of readers and the number of writers accessing the database. The following condition should be true for all states: Good States (nr == 0 and nw <= 1) or nw == 0
A skeleton int nr = 0, nw = 0 process Reader[i = 1 to m] while(true) #ATOMIC: await (nw==0) # read! #ATOMIC: nr = nr-1 then nr = nr+1 process Writer[j = 1 to n] while(true) #ATOMIC: await (nr==0 and nw==0) then nw = nw+1 # write! #ATOMIC: nw=nw-1
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 to one other process: If some process is waiting for a condition that is now 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 to one other process: If some process is waiting for a condition that is now 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 to one other process: If some process is waiting for a condition that is now 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 to one other process: If some process is waiting for a condition that is now 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 to one other process: If some process is waiting for a condition that is now 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 if(dr>0) {dr=dr-1;v(r) else {V(e)
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 if(dr>0) {dr=dr-1;v(r) else {V(e)
Implementing atomic waiting on conditions nr = nr-1 P(e) nr = nr-1 if(nr==0 and dw>0) {dw=dw-1;v(w) else {V(e)
Implementing atomic waiting on conditions nr = nr-1 P(e) nr = nr-1 if(nr==0 and dw>0) {dw=dw-1;v(w) else {V(e)
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 V(e)
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 V(e)
Implementing atomic waiting on conditions P(e) nw = nw-1 if(dr>0) {dr=dr-1;v(r) elseif(dw>0){dw=dw-1;v(w) else {V(e) nw = nw-1
Implementing atomic waiting on conditions P(e) nw = nw-1 if(dr>0) {dr=dr-1;v(r) elseif(dw>0){dw=dw-1;v(w) else {V(e) nw = nw-1
Lizards
Recap Screens Readers & Writers Monitors
Submarines
A language approach to synchronization
An Abstract Data Type... Example class Counter{ private int x = 0; Example resource Counter op inc() body Counter() public void inc(){ int tmp = x; Support.nap(10); tmp++; Support.nap(10); x = tmp; 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; Example resource Counter op inc() body Counter() public void inc(){ int tmp = x; Support.nap(10); tmp++; Support.nap(10); x = tmp; 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; Example resource Counter op inc() body Counter() public void inc(){ int tmp = x; Support.nap(10); tmp++; Support.nap(10); x = tmp; int x = 0 proc inc(){ int tmp = x nap(10);tmp++;nap(10) x = tmp end
... that supports Mutual Exclusion Example import 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) end
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 the monitor. 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 the monitor. 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 the monitor. 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 the monitor. 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 the monitor. 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 elaborate abstract data types, threads might need to be blocked until some condition holds for the abstract datatype. Example In the bounded buffer that is shared by producer threads and consumer threads: Producers might have to wait until the buffer is not full. Consumers might have to wait until the buffer is not empty. Languages supporting monitors provide a type for condition 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 elaborate abstract data types, threads might need to be blocked until some condition holds for the abstract datatype. Example In the bounded buffer that is shared by producer threads and consumer threads: Producers might have to wait until the buffer is not full. Consumers might have to wait until the buffer is not empty. Languages supporting monitors provide a type for condition 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 elaborate abstract data types, threads might need to be blocked until some condition holds for the abstract datatype. Example In the bounded buffer that is shared by producer threads and consumer threads: Producers might have to wait until the buffer is not full. Consumers might have to wait until the buffer is not empty. Languages supporting monitors provide a type for condition 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 elaborate abstract data types, threads might need to be blocked until some condition holds for the abstract datatype. Example In the bounded buffer that is shared by producer threads and consumer threads: Producers might have to wait until the buffer is not full. Consumers might have to wait until the buffer is not empty. Languages supporting monitors provide a type for condition 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 elaborate abstract data types, threads might need to be blocked until some condition holds for the abstract datatype. Example In the bounded buffer that is shared by producer threads and consumer threads: Producers might have to wait until the buffer is not full. Consumers might have to wait until the buffer is not empty. Languages supporting monitors provide a type for condition 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. How? Awaken a delayed process when the property holds. 1 Inside a monitor declare a variable of the type for condition variables cond cv. 2 A process blocks on a condition variable by executing wait(cv). 3 Processes that are blocked on condition variables get 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. How? Awaken a delayed process when the property holds. 1 Inside a monitor declare a variable of the type for condition variables cond cv. 2 A process blocks on a condition variable by executing wait(cv). 3 Processes that are blocked on condition variables get 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. How? Awaken a delayed process when the property holds. 1 Inside a monitor declare a variable of the type for condition variables cond cv. 2 A process blocks on a condition variable by executing wait(cv). 3 Processes that are blocked on condition variables get 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. How? Awaken a delayed process when the property holds. 1 Inside a monitor declare a variable of the type for condition variables cond cv. 2 A process blocks on a condition variable by executing wait(cv). 3 Processes that are blocked on condition variables get 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. How? Awaken a delayed process when the property holds. 1 Inside a monitor declare a variable of the type for condition variables cond cv. 2 A process blocks on a condition variable by executing wait(cv). 3 Processes that are blocked on condition variables get 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. How? Awaken a delayed process when the property holds. 1 Inside a monitor declare a variable of the type for condition variables cond cv. 2 A process blocks on a condition variable by executing wait(cv). 3 Processes that are blocked on condition variables get 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. How? Awaken a delayed process when the property holds. 1 Inside a monitor declare a variable of the type for condition variables cond cv. 2 A process blocks on a condition variable by executing wait(cv). 3 Processes that are blocked on condition variables get awaken by signal(cv).
Semantics Values The value of a condition variable is a queue of delayed processes. Wait The process that executes wait(cv) gets delayed at the rear of the queue for cv. It relinquishes exclusive access to the monitor. Signal Execution of signal(cv) examines cv 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 The value of a condition variable is a queue of delayed processes. Wait The process that executes wait(cv) gets delayed at the rear of the queue for cv. It relinquishes exclusive access to the monitor. Signal Execution of signal(cv) examines cv 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 The value of a condition variable is a queue of delayed processes. Wait The process that executes wait(cv) gets delayed at the rear of the queue for cv. It relinquishes exclusive access to the monitor. Signal Execution of signal(cv) examines cv 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 The value of a condition variable is a queue of delayed processes. Wait The process that executes wait(cv) gets delayed at the rear of the queue for cv. It relinquishes exclusive access to the monitor. Signal Execution of signal(cv) examines cv 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 - signaling disciplines Who will get to run when a process does signal(cv)? The signaling process? The newly awaken process? Signal and Continue The signaler continues, the signaled process executes at some later time. Signal and Wait The signaler waits until some other time and the signaled process executes now. Signal and Continue is 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 does signal(cv)? The signaling process? The newly awaken process? Signal and Continue The signaler continues, the signaled process executes at some later time. Signal and Wait The signaler waits until some other time and the signaled process executes now. Signal and Continue is 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 does signal(cv)? The signaling process? The newly awaken process? Signal and Continue The signaler continues, the signaled process executes at some later time. Signal and Wait The signaler waits until some other time and the signaled process executes now. Signal and Continue is 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 does signal(cv)? The signaling process? The newly awaken process? Signal and Continue The signaler continues, the signaled process executes at some later time. Signal and Wait The signaler waits until some other time and the signaled process executes now. Signal and Continue is implemented in Unix, Java and PThreads. It is compatible with priority scheduling, programs are easier to understand.
What we don t see...
java.util.concurrent.locks Monitors (locks and condition types) are provided in the package java.util.concurrent.locks The interface Condition 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 interface Condition 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 A Condition instance is intrinsically bound to a lock. To obtain a Condition instance 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 A Condition instance is intrinsically bound to a lock. To obtain a Condition instance 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 Example public 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 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 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 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 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 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 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 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 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 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 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 database
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(); Can writers starve?
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();