Concurrency Monitors and Condition Synchronization Claus Brabrand

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

Operating Systems: Monitors 1 Monitors (C.A.R. Hoare) higher level construct than semaphores a package of grouped procedures, variables and data i.e. object.
– R 7 :: 1 – 0024 Spring 2010 Parallel Programming 0024 Recitation Week 7 Spring Semester 2010.
1 Chapter 5 Concurrency: Mutual Exclusion and Synchronization Principals of Concurrency Mutual Exclusion: Hardware Support Semaphores Readers/Writers Problem.
Ch 7 B.
Concurrency Important and difficult (Ada slides copied from Ed Schonberg)
Chapter 6: Process Synchronization
5.1 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts with Java – 8 th Edition Chapter 5: CPU Scheduling.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
Concurrency: monitors & condition synchronization1 ©Magee/Kramer 2 nd Edition Chapter 5 Monitors & Condition Synchronization.
Concurrency: monitors & condition synchronization1 ©Magee/Kramer 2 nd Edition COMP60611 Fundamentals of Parallel and Distributed Systems Lecture 8b Monitors.
Monitors Chapter 7. The semaphore is a low-level primitive because it is unstructured. If we were to build a large system using semaphores alone, the.
CS 11 java track: lecture 7 This week: Web tutorial:
© Andy Wellings, 2004 Roadmap  Introduction  Concurrent Programming  Communication and Synchronization  Completing the Java Model  Overview of the.
5.6 Semaphores Semaphores –Software construct that can be used to enforce mutual exclusion –Contains a protected variable Can be accessed only via wait.
Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Process Synchronization (Or The “Joys” of Concurrent.
Lars A. Conrad-Hansen, Introduction to Multimedia Systems Multitasking & Synchronization.
Synchronization in Java Nelson Padua-Perez Bill Pugh Department of Computer Science University of Maryland, College Park.
Semaphores CSCI 444/544 Operating Systems Fall 2008.
Synchronization in Java Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Concurrency: Deadlock ©Magee/Kramer Claus Brabrand University of Aarhus Deadlock Concurrency.
Race Conditions CS550 Operating Systems. Review So far, we have discussed Processes and Threads and talked about multithreading and MPI processes by example.
Concurrency - 1 Tasking Concurrent Programming Declaration, creation, activation, termination Synchronization and communication Time and delays conditional.
Instructor: Umar KalimNUST Institute of Information Technology Operating Systems Process Synchronization.
Threads II. Review A thread is a single flow of control through a program Java is multithreaded—several threads may be executing “simultaneously” If you.
Parallel Processing (CS526) Spring 2012(Week 8).  Thread Status.  Synchronization in Shared Memory Programming(Java threads ) ◦ Locks ◦ Barriars.
Monitor  Giving credit where it is due:  The lecture notes are borrowed from Dr. I-Ling Yen at University of Texas at Dallas  I have modified them and.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Operating Systems CMPSCI 377 Lecture.
1 Processes, Threads, Race Conditions & Deadlocks Operating Systems Review.
6.3 Peterson’s Solution The two processes share two variables: Int turn; Boolean flag[2] The variable turn indicates whose turn it is to enter the critical.
Operating Systems CMPSC 473 Mutual Exclusion Lecture 14: October 14, 2010 Instructor: Bhuvan Urgaonkar.
Semaphores, Locks and Monitors By Samah Ibrahim And Dena Missak.
4061 Session 21 (4/3). Today Thread Synchronization –Condition Variables –Monitors –Read-Write Locks.
CSC321 Concurrent Programming: §5 Monitors 1 Section 5 Monitors.
Silberschatz, Galvin and Gagne  Operating System Concepts Chapter 7: Process Synchronization Background The Critical-Section Problem Synchronization.
ICS 313: Programming Language Theory Chapter 13: Concurrency.
Advanced Concurrency Topics Nelson Padua-Perez Bill Pugh Department of Computer Science University of Maryland, College Park.
Synchronizing Threads with Semaphores
1 Interprocess Communication (IPC) - Outline Problem: Race condition Solution: Mutual exclusion –Disabling interrupts; –Lock variables; –Strict alternation.
Chapter 5 Concurrency: Mutual Exclusion and Synchronization Operating Systems: Internals and Design Principles, 6/E William Stallings Patricia Roy Manatee.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Synchronization.
1 CMSC421: Principles of Operating Systems Nilanjan Banerjee Principles of Operating Systems Acknowledgments: Some of the slides are adapted from Prof.
TANNENBAUM SECTION 2.3 INTERPROCESS COMMUNICATION3 OPERATING SYSTEMS.
Monitors and Blocking Synchronization Dalia Cohn Alperovich Based on “The Art of Multiprocessor Programming” by Herlihy & Shavit, chapter 8.
Today’s Agenda  Quick Review  Semaphore and Lock Advanced Topics in Software Engineering 1.
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for.
6.1 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts with Java – 8 th Edition Module 6: Process Synchronization Codes.
Comunication&Synchronization threads 1 Programación Concurrente Benemérita Universidad Autónoma de Puebla Facultad de Ciencias de la Computación Comunicación.
Threads in Java Threads Introduction: After completing this chapter, you will be able to code your own thread, control them efficiently without.
Silberschatz, Galvin and Gagne ©2013 Operating System Concepts – 9 th Edition Chapter 5: Process Synchronization.
CSC321 §8 Implementing FSP Models in Java 1 Section 8 Implementing FSP Models in Java.
Chien-Chung Shen CIS/UD
Background on the need for Synchronization
Condition Synchronization
Monitors Chapter 7.
Lecture 9: Process Synchronization
Condition Variables and Producer/Consumer
Condition Variables and Producer/Consumer
Thread Synchronization
Process Synchronization
Multithreading.
Background Concurrent access to shared data can lead to inconsistencies Maintaining data consistency among cooperating processes is critical What is wrong.
Monitors Chapter 7.
Concurrency: Mutual Exclusion and Process Synchronization
Monitors Chapter 7.
Monitor Giving credit where it is due:
Chapter 6 Synchronization Principles
CSE 153 Design of Operating Systems Winter 2019
Presentation transcript:

Concurrency Monitors and Condition Synchronization Claus Brabrand brabrand@daimi.au.dk University of Aarhus

Condition Synchronization Agenda Condition Synchronization CarPark Semaphores SemaDemo Producer/Consumer Bounded Buffer Demo The Nested Monitor Problem

Condition Synchronization Chapter 5 Monitors & Condition Synchronization

Monitors & Condition Synchronization Concepts: monitors: encapsulated data + access procedures + mutual exclusion + condition synchronization + single access procedure active in the monitor nested monitors (“nested monitor problem”) Models: guarded actions Practice: private data and synchronized methods (exclusion). wait(), notify() and notifyAll() for condition synch. single thread active in the monitor at a time

Condition Synchronization

5.1 Condition Synchronization (Car Park) A controller is required to ensure:  cars can only enter when not full  cars can only leave when not empty (duh!)

Car Park Model (Actions and Processes) Actions of interest: arrive depart Identify processes: Arrivals Departures Control env

Car Park Model (Structure Diagram) Actions of interest: arrive depart Identify processes: Arrivals Departures Control env ARRIVALS CARPARK CONTROL DEPARTURES arrive depart

Guarded actions are used to control arrive and depart Car Park Model (FSP) ARRIVALS CARPARK CONTROL DEPARTURES arrive depart ARRIVALS = (arrive -> ARRIVALS). DEPARTURES = (depart -> DEPARTURES). CONTROL(N=4) = SPACES[N], SPACES[i:0..N] = (when(i>0) arrive -> SPACES[i-1] |when(i<N) depart -> SPACES[i+1]). ||CARPARK = (ARRIVALS || DEPARTURES || CONTROL(4)). Guarded actions are used to control arrive and depart LTS? What if we remove ARRIVALS and DEPARTURES?

For the carpark? Car Park Program Model - all entities are processes interacting via shared actions Program - need to identify threads and monitors: thread - active entity which initiates (output) actions monitor - passive entity which responds to (input) actions. For the carpark?  Arrivals:  Departures:  Control: active => thread passive => monitor

Car Park Program (Interesting part of Class Diagram) Arrivals Departures Runnable Control arrive() depart() carpark Active (thread) Active (thread) Passive (monitor)

The Control is shared by Arrival and Departures threads Car Park Program - Main Arrivals Departures Runnable Control arrive() depart() carpark The main() method creates:  Control monitor  Arrival thread  Departures thread public static void main(String[] args) { Control c = new Control(PLACES); arrivals = new Thread(new Arrivals(c)); departures = new Thread(new Departures(c)); arrivals.start(); departures.start(); } The Control is shared by Arrival and Departures threads

Car Park Program - Arrivals ARRIVALS = (arrive -> ARRIVALS). class Arrivals implements Runnable { Control carpark; Arrivals(Control c) { carpark = c; } public void run() { try { while(true) { Thread.sleep(...); carpark.arrive(); } } catch (InterruptedException _) {} Would like to somehow block Arrival thread here… … similarly for Departures (calling carpark.depart()) Where should we do the “blocking”? How do we implement the Carpark Controller’s control?

Encapsulation ~ protected CONTROL(N=4) = SPACES[N], SPACES[i:0..N] = (when(i>0) arrive -> SPACES[i-1] |when(i<N) depart -> SPACES[i+1]). Control Monitor class Control { int spaces, capacity; Control(int n) { capacity = spaces = n; } void arrive() { ... --spaces; ... void depart() { ... ++spaces; ... Encapsulation ~ protected protected Mutual exclusion ~ synchronized Condition synchronization: synchronized Block, if full? (spaces==0) synchronized Block, if empty? (spaces==N)

Condition Synchronization in Java Java provides a thread wait queue per object (not per class). Object has methods: public final void wait() throws InterruptedException; Waits to be notified ; Releases the synchronization lock associated with the obj. When notified, the thread must reacquire the synchr. lock. public final void notify(); public final void notifyAll(); Wakes up (notifies) thread(s) waiting on the object’s queue.

Condition Synchronization in Java (enter/exit) A thread:  Enters a monitor when a thread acquires the lock associated with the monitor;  Exits a monitor when it releases the lock. Wait() causes the thread to exit the monitor, permitting other threads to enter the monitor Thread A Thread B wait() notify() Monitor data

Condition Synchronization in FSP and Java FSP: when (cond) action -> NEWSTATE synchronized void action() throws Int’Exc’ { while (!cond) wait(); // modify monitor data notifyAll(); } The while loop is necessary to re-test the condition cond to ensure that cond is indeed satisfied when it re-enters the monitor. notifyAll() is necessary to awaken other thread(s) that may be waiting to enter the monitor now that the monitor data has been changed.

CarParkControl - Condition Synchronization CONTROL(N=4) = SPACES[N], SPACES[i:0..N] = (when(i>0) arrive -> SPACES[i-1] |when(i<N) depart -> SPACES[i+1]). class Control { protected int spaces, capacity; synchronized void arrive() throws Int’Exc’ { while (!(spaces>0)) wait(); --spaces; notifyAll(); } synchronized void depart() throws Int’Exc’ { while (!(spaces<capacity)) wait(); ++spaces; Why might it be sensible here to use notify() rather than notifyAll()?

Models to Monitors - Guidelines  Active entities (that initiate actions) are implemented as threads.  Passive entities (that respond to actions) are implemented as monitors. Each guarded action in the model of a monitor is implemented as a synchronized method which uses a while loop and wait() to implement the guard. The while loop condition is the negation of the model guard condition. Changes in the state of the monitor are signalled to waiting threads using notifyAll() (or notify()).

Semaphores

5.2 Semaphores Semaphores are widely used for dealing with inter-process synchronization in operating systems. Semaphore s : integer var that can take only non-neg. values. s.down(): when s>0 do decrement(s); Aka. “P” ~ Passern s.up(): increment(s); Aka. “V” ~ Vrijgeven Usually implemented as blocking wait: s.down(): if (s>0) then decrement(s); else block execution of calling process s.up(): if (processes blocked on s) then awake one of them else increment(s);

Modelling Semaphores To ensure analyzability, we only model semaphores that take a finite range of values. If this range is exceeded then we regard this as an ERROR. const Max = 3 range Int = 0..Max SEMAPHORE(N=0) = SEMA[N], // N initial value SEMA[v:Int] = (up->SEMA[v+1] |when(v>0) down->SEMA[v-1]), SEMA[Max+1] = ERROR. LTS? What if we omit the last line above?

Modelling Semaphores Action down is only accepted when value (v) of the semaphore is greater than 0. Action up is not guarded. Trace to a violation: up  up  up  up

LOOP = (mutex.down->critical->mutex.up->LOOP). SEMAPHORE(N=0) = SEMA[N], // N initial value SEMA[v:Int] = (up->SEMA[v+1] |when(v>0) down->SEMA[v-1]), Semaphore Demo - Model Three processes p[1..3] use a shared semaphore mutex to ensure mutually exclusive access (action “critical”) to some resource. LOOP = (mutex.down->critical->mutex.up->LOOP). ||SEMADEMO = (p[1..3]:LOOP || {p[1..3]}::mutex:SEMAPHORE(1)). For mutual exclusion, the semaphore initial value is 1. Why? Is the ERROR state reachable for SEMADEMO? Is a binary semaphore sufficient (i.e. Max=1) ? LTS?

Semaphore Demo - Model

Semaphores in Java SEMA[v:Int] = (when(v>0) down->SEMA[v-1] | up->SEMA[v+1]), public class Semaphore { protected int value; public Semaphore (int n) { value = n; } synchronized public void down() throws Int’Exc’ { while (!(value > 0)) wait(); --value; notifyAll(); } synchronized public void up() { ++value; Do we need notifyAll() here? …what about here?

SEMADEMO Display

SEMADEMO Program - MutexLoop LOOP = (mutex.down->critical->mutex.up->LOOP). SEMADEMO Program - MutexLoop class MutexLoop implements Runnable { Semaphore mutex; // shared semaphore MutexLoop (Semaphore sem) { mutex=sem; } public void run() { try { while(true) { // non-critical action mutex.down(); // acquire // critical action mutex.up(); // release } } catch(InterruptedException _) {} However (in practice), semaphore is a low-level mechanism often used in implementing higher-level monitor constructs.

Producer / Consumer

5.3 Producer / Consumer A bounded buffer consists of a fixed number of slots. Items are put into the buffer by a producer process and removed by a consumer process: ≈ Car Park Example!

Producer / Consumer - a Data-Independent Model BUFFER CONSUMER put get BOUNDEDBUFFER The behaviour of BOUNDEDBUFFER is independent of the actual data values, and so can be modelled in a data-independent manner (i.e., we abstract away the letters). LTS?

Producer / Consumer PRODUCER = (put->PRODUCER). CONSUMER = (get->CONSUMER). BUFFER(N=5) = COUNT[0], COUNT[i:0..N] = (when (i<N) put->COUNT[i+1] |when (i>0) get->COUNT[i-1]). ||BOUNDEDBUFFER = (PRODUCER || BUFFER(5) || CONSUMER). PRODUCER BUFFER CONSUMER put get BOUNDEDBUFFER

Bounded Buffer Program - Buffer Monitor BUFFER(N=5) = COUNT[0], COUNT[i:0..N] = (when (i<N) put->COUNT[i+1] |when (i>0) get->COUNT[i-1]). public interface Buffer { public void put(Object o) throws InterruptedException; public Object get() throws InterruptedException; } class BufferImpl implements Buffer { protected Object[] buf; protected int in, out, count, size; … synchronized void put(Object o) throws Int’Exc’ { while (!(count<size)) wait(); buf[in] = o; count++; in = (in+1) % size; notifyAll(); }

Similarly for get() BUFFER(N=5) = COUNT[0], COUNT[i:0..N] = (when (i<N) put->COUNT[i+1] |when (i>0) get->COUNT[i-1]). public interface Buffer { public void put(Object o) throws InterruptedException; public Object get() throws InterruptedException; } synchronized Object get() throws Int’Exc’ { 1. while (!(count>0)) wait(); 2. Object obj = buf[out]; 3. buf[out] = null; 4. count--; 5. out = (out+1) % size; 6. notifyAll(); 7. return obj; }  What happens if we move notifyAll() up earlier (e.g. as line 2)?  What is the point of line 3?

Producer Process class Producer implements Runnable { Buffer buf; PRODUCER = (put->PRODUCER). class Producer implements Runnable { Buffer buf; String alpha = "abcdefghijklmnopqrstuvwxyz"; Producer(Buffer b) { buf = b; } public void run() { try { int i = 0; while(true) { Thread.sleep(...); buf.put(new Character(alpha.charAt(i))); i=(i+1) % alpha.length(); } } catch (InterruptedException _) {} Similarly Consumer which calls buf.get()

The Nested Monitor Problem

5.4 Nested Monitors (Semaphores) Suppose that, instead of using the count variable and condition synchronization, we instead use 2 semaphores full and empty to reflect the state of the buffer: class SemaBuffer implements Buffer { protected Object buf[]; protected int in, out, count, size; Semaphore empty; // block get appropriately Semaphore full; // block put appropriately SemaBuffer(int s) { size = s; in = out = count = 0; buf = new Object[size]; empty = new Semaphore(0); full = new Semaphore(size); }

Nested Monitors Program synchronized public void put(Object o) throws Int’Exc’ { full.down(); buf[in] = o; count++; in = (in+1) % size; empty.up(); } synchronized public Object get() throws Int’Exc’ { empty.down(); Object o = buf[out]; buf[out] = null; count--; out = (out+1) % size; full.up(); return o; full is decremented during a put, which is blocked if full is zero. empty is decremented by a get, which is blocked if empty is zero. Does this behave as desired?

Nested Monitors Model PRODUCER = (put -> PRODUCER). synchronized public void put(Object o) throws Int’Exc’ { full.down(); buf[in] = o; count++; in = (in+1) % size; empty.up(); } Nested Monitors Model PRODUCER = (put -> PRODUCER). CONSUMER = (get -> CONSUMER). SEMAPHORE(N=0) = SEMA[N], SEMA[v:Int] = (when(v>0) down->SEMA[v-1] | up->SEMA[v+1]). BUFFER = (put -> full.down -> p -> empty.up -> BUFFER |get -> empty.down -> g -> full.up -> BUFFER). ||BOUNDEDBUFFER = ( PRODUCER || BUFFER || CONSUMER || full:SEMAPHORE(5) || empty:SEMAPHORE(0) ). Does this behave as desired?

LTSA analysis predicts a DEADLOCK: synchronized public Object get() throws Int’Exc’ { empty.down(); Object o = buf[out]; buf[out] = null; count--; out = (out+1) % size; full.up(); return o; } Nested Monitors LTSA analysis predicts a DEADLOCK: Composing potential DEADLOCK States Composed: 28 Transitions: 32 in 60ms Trace to DEADLOCK: get Initially Consumer calls SemaBuffer.get(), acquiring a synchr’ lock (on the buffer); Semaphore.down() - acquires another synchronization lock (on the Semaphore); Semaphore.down() - releases its lock using wait() (but only this lock)! This situation is known as the nested monitor problem!

Nested Monitors - Revised Bounded Buffer Program The only way to avoid it in Java is by careful design : synchronized public void put(Object o) throws Int’Exc’ { full.down(); buf[in] = o; count++; in = (in+1) % size; empty.up(); } public void put(Object o) throws Int’Exc’ { full.down(); synchronized (this) { buf[in] = o; count++; in = (in+1) % size; } empty.up(); In this example, the deadlock can be removed by ensuring that the monitor lock for the buffer is not acquired until after semaphores are decremented.

Nested Monitors - Revised Bounded Buffer Model The semaphore actions have been moved outside the monitor (i.e., conceptually, to the producer and consumer): BUFFER = (put -> BUFFER |get -> BUFFER). PRODUCER = (full.down -> put -> empty.up -> PRODUCER). CONSUMER = (empty.down -> get -> full.up -> CONSUMER). Does this behave as desired? No deadlocks/errors

INV(CarParkControl): 0  spaces  N INV(Semaphore): 0  value 5.5 Monitor invariants An invariant for a monitor is an assertion concerning the variables it encapsulates. This assertion must hold whenever there is no thread executing inside the monitor i.e. on thread entry to and exit from a monitor . INV(CarParkControl): 0  spaces  N INV(Semaphore): 0  value INV(Buffer): 0  count  size and 0  in < size and 0  out < size and in = (out + count) % size Like normal invariants, but must also hold when lock is released (wait)!

Models: guarded actions Summary Concepts: monitors: encapsulated data + access procedures + mutual exclusion + condition synchronization + single access procedure active in the monitor nested monitors Models: guarded actions Practice: private data and synchronized methods (exclusion). wait(), notify() and notifyAll() for condition synch. single thread active in the monitor at a time