Java Monitors Parallel and Distributed Computing Department of Computer Science and Engineering (DEI) Instituto Superior Técnico October 19, 2010 Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 1 / 1
Outline Mutual Exclusion Monitors vs Semaphores Java Monitors Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 2 / 1
SMP Programming Errors Shared Memory parallel programming: saves the programmer from having to map data onto multiple processors. opens up a range of new errors coming from unanticipated shared resource conflicts Race Conditions The output of a program depends on the timing of the threads in the team. Deadlock Threads lock up on a locked resource that will never become free. Livelock Threads working on individual tasks which the ensemble cannot finish. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 3 / 1
Race Conditions Insert a node into a doubly-linked list newnode->prev = node; newnode->next = node->next; node->next->prev = newnode; node->next = newnode; Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 4 / 1
Race Conditions Insert a node into a doubly-linked list newnode->prev = node; newnode->next = node->next; node->next->prev = newnode; node->next = newnode; Simple counter increment counter++; Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 4 / 1
Critical Regions Critical Region Sections of the code that access a shared resource which must not be accessed concurrently by another thread. non-critical entry region critical-region leave region non-critical Unfortunate notation: the critical region is really in data but the guards are in code Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 5 / 1
Mutual Exclusion Mutex: mechanism that performs the check that a critical region is free. A mutex has two states, that are usually referred to as unlocked and locked: an unlocked mutex indicates that the critical region is empty a locked mutex indicates that there is some thread inside the critical region All threads must check the state of the mutex before entering the critical region! Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 6 / 1
Mutual Exclusion in OpenMP int cnt = 0; #pragma omp parallel { #pragma omp for for(i = 0; i < 20; i++) { if(b[i] == 0) { #pragma omp critical (cnt zeros) { cnt++; /* endif */ a[i] = b[i] * (i+1); /* end for */ /*omp end parallel */ Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 7 / 1
Mutex Implementation Simple implementation of mutex using semaphores: Wait(S) (ie, Lock) if (S > 0) then S = S - 1 else suspend execution of this thread Signal(S) (ie, Unlock) if there are processes suspended on this semaphore then wake one of them else S = S + 1 Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 8 / 1
Monitors Semaphores are low-level synchronization primitives, inherently unstructured usage of the semaphore must be correct for all regions of the program Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 9 / 1
Monitors Semaphores are low-level synchronization primitives, inherently unstructured usage of the semaphore must be correct for all regions of the program Monitors provide a structured concurrent programming primitive that concentrates the responsibility of correctness to a few modules. Monitors encapsulate: items of data procedures that operate on this set of data In object-oriented programming, monitors synchronize calls to the methods of a class. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 9 / 1
Monitor Concept Already in the 1970s concurrent programmers were faced with the following problems: Concurrent programs were unreliable and hard to write Semaphores were already understood but semaphores were often used incorrectly and a compiler could provide no help on using them Brinch-Hansen and Hoare proposed monitors, which: provide the facility for synchronizing concurrent programs that would be easy to use and could also be checked by a compiler when threads (process) have to access the same variables, they must be granted mutually exclusive access one thread must be able to wait for a condition that another thread can cause without creating a deadlock situation Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 10 / 1
Monitors Monitor A monitor is essentially a shared class with explicit queues. A monitor region is code that needs to be executed as one indivisible operation with respect to a particular monitor. A monitor enforces this one-thread-at-a-time execution of its monitor regions. The only way a thread can enter a monitor is by arriving at the beginning of one of the monitor regions associated with that monitor. The only way a thread can move forward and execute the monitor region is by acquiring the monitor. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 11 / 1
Monitors When a thread arrives at the beginning of a monitor region, it is placed into an entry set for the associated monitor. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 12 / 1
Monitors When a thread arrives at the beginning of a monitor region, it is placed into an entry set for the associated monitor. When the thread finishes executing the monitor region, it exits and releases the monitor. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 12 / 1
Monitors When a thread arrives at the beginning of a monitor region, it is placed into an entry set for the associated monitor. When the thread finishes executing the monitor region, it exits and releases the monitor. A thread can suspend itself inside the monitor by executing a wait command. When a thread executes a wait, it releases the monitor and enters a wait set. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 12 / 1
Monitors When a thread arrives at the beginning of a monitor region, it is placed into an entry set for the associated monitor. When the thread finishes executing the monitor region, it exits and releases the monitor. A thread can suspend itself inside the monitor by executing a wait command. When a thread executes a wait, it releases the monitor and enters a wait set. The thread will stay suspended in the wait set until some time after another thread executes a notify command inside the monitor. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 12 / 1
Monitors When a thread arrives at the beginning of a monitor region, it is placed into an entry set for the associated monitor. When the thread finishes executing the monitor region, it exits and releases the monitor. A thread can suspend itself inside the monitor by executing a wait command. When a thread executes a wait, it releases the monitor and enters a wait set. The thread will stay suspended in the wait set until some time after another thread executes a notify command inside the monitor. When a thread executes a notify, it continues to own the monitor until it releases the monitor of its own accord, either by executing a wait or by completing the monitor region. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 12 / 1
Simple Monitor Operation Entry Set The Owner Wait Set enter acquire release acquire release and exit Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 13 / 1
Simple Monitor Operation Entry Set The Owner Wait Set enter acquire release acquire release and exit Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 13 / 1
Simple Monitor Operation Entry Set The Owner Wait Set enter acquire release acquire release and exit Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 13 / 1
Simple Monitor Operation Entry Set The Owner Wait Set enter acquire release acquire release and exit Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 13 / 1
Simple Monitor Operation Entry Set The Owner Wait Set enter acquire release acquire release and exit Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 13 / 1
Simple Monitor Operation Entry Set The Owner Wait Set enter acquire release acquire release and exit Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 13 / 1
Simple Monitor Operation Entry Set The Owner Wait Set enter acquire release acquire release and exit Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 13 / 1
Three Types of Monitors Brinch-Hansen and Hoare Signal and continue Java monitor graphics by Theodore Norvell Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 14 / 1
Design Goals of Java Simple programmed without extensive programmer training Object oriented libraries of tested objects that provide functionality ranging from basic data types through I/O and network interfaces to graphical user interface toolkits. Familiar look and feel of C++ without the unnecessary complexities of C++ programmers can easily migrate from C++ Multithreaded library provides the Thread class the run-time system provides monitor and condition lock primitives high-level system libraries have been written to be thread safe Dynamic classes are linked only as needed code modules can be linked in on demand Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 15 / 1
Design Goals of Java Architectural neutral and portable generation of bytecodes programs are the same on every platform High Performance interpreter can run at full speed without needing to check the run-time environment automatic garbage collector runs as a low-priority background thread Robust extensive compile-time checking memory management model is extremely simple no pointer arithmetic automatic garbage collection Secure security features designed into the language and run-time system Distributed portable across multiple machine architectures, operating systems, and graphical user interfaces, secure, and high performance Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 16 / 1
Simple Example public class Point { protected int x_coord; protected int y_coord; public Point () { place(0, 0); public Point (int x, int y) { place(x, y); public int getx () { return x_coord; public int gety () { return y_coord; public void place (int x, int y) { x_coord = x; y_coord = y; public void move (int x, int y) { x_coord += x; y_coord += y; Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 17 / 1
Simple Example public class Point { protected int x_coord; protected int y_coord; public Point () { place(0, 0); public Point (int x, int y) { place(x, y); public int getx () { return x_coord; public int gety () { return y_coord; public void place (int x, int y) { x_coord = x; y_coord = y; public void move (int x, int y) { x_coord += x; y_coord += y; public class Circle extends Point { protected int radius; public Circle() { setradius(0); public Circle(int x, int y, int r) { super(x, y); radius = r; public int getradius () { return radius; public int setradius (int r) { radius = r; public int enlarge (int r) { radius *= r; public float area () { return Math.PI * radius * radius; Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 17 / 1
Threads in Java Threads in Java are integrated into the language. class dummythread extends Thread { int id; public dummythread(int id) {this.id = id; public void run(){ System.out.println("Hello World from thread "+id); dummythread dt = new dummythread(42); dt.start(); dt.join(); Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 18 / 1
Threads in Java Local variables Every thread has its own set of local variables stored in a stack frame, to which no other thread has access. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 19 / 1
Threads in Java Local variables Every thread has its own set of local variables stored in a stack frame, to which no other thread has access. wait, notify and sleep used for inter-thread communication: Thread.wait, goes to sleep until some other thread wakes it up. Thread.notify, wakes up some other thread. Thread.sleep, goes to sleep for some specified number of milliseconds, unless some other thread wakes it up first. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 19 / 1
Threads in Java Local variables Every thread has its own set of local variables stored in a stack frame, to which no other thread has access. wait, notify and sleep used for inter-thread communication: Thread.wait, goes to sleep until some other thread wakes it up. Thread.notify, wakes up some other thread. Thread.sleep, goes to sleep for some specified number of milliseconds, unless some other thread wakes it up first. interrupt One thread can interrupt another with Thread.interrupt. The most common use is to wake up a sleeping thread prematurely, or to abort a long I/O. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 19 / 1
Mutex in Java Mutual exclusion is straightforward in Java: attribute synchronized. synchronized doit() { /* critical section */ The synchronized attribute ensures that a single thread will be executing method doit() at any time. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 20 / 1
Example: Producer-Consumer Problem Construct a FIFO from a finite length buffer: only two operations: append and remove append and remove exclude each other a producer should suspend on a full buffer a consumer should suspend on an empty buffer Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 21 / 1
Producer-Consumer with Semaphores void producer() { int item; while (TRUE) { item = produce_item(); /* claim empty spot */ sem_wait(¬_full); sem_wait(&mutex); /* insert, protected by mutex */ insert_item(item); sem_post(&mutex); /* signal filled-in spot */ sem_post(¬_empty); void consumer() { int item; while (TRUE) { /* claim spot in buffer */ sem_wait(¬_empty); sem_wait(&mutex); /* remove, protected by mutex */ item = remove_item(); sem_post(&mutex); /* signal empty spot */ sem_post(¬_full); consume_item(item); Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 22 / 1
Producer-Consumer with Java Monitors class Buffer { private Object[] buf; private int in = 0; //index for put private int out = 0; //index for get private int count = 0; //no of items private int size; Buffer(int size) { this.size = size; buf = new Object[size]; synchronized public void put(object o) {... synchronized public Object get() {... Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 23 / 1
Producer-Consumer with Java Monitors synchronized public void put(object o) { while (count >= size) { try { wait(); catch(interruptedexception e){ buf[in] = o; ++count; in = (in + 1) % size; notifyall(); synchronized public Object get() { while (count == 0) { try { wait(); catch (InterruptedException e){ Object o = buf[out]; buf[out] = null; // display purposes --count; out = (out + 1) % size; notifyall(); // [count < size] return (o); Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 24 / 1
Producer-Consumer with Java Monitors Solution is more structured than semaphores: data and procedures are encapsulated in a single module mutual exclusion is provided automatically by the implementation producer and consumer processes see only abstract put and get Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 25 / 1
Limitations of Previous Approach only one queue for threads waiting at an object must always wake up all of the waiting threads Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 26 / 1
Limitations of Previous Approach only one queue for threads waiting at an object must always wake up all of the waiting threads the thread awakened by notify() or notifyall() does not get immediate control of the lock. By the time the thread runs, the condition may no longer be true, so it must check the condition again. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 26 / 1
Classes Lock and Condition Class Lock provides exclusive access to a shared resource by multiple threads may support multiple associated Condition objects more flexible structuring and more extensive locking operations than using synchronized statement Class Condition factors out the Object monitor methods (wait, notify and notifyall) into distinct objects provides a means for one thread to suspend execution until notified by another thread that some state condition may now be true is intrinsically bound to a lock Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods. Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 27 / 1
Solution using Class Conditions class Buffer { private final ReentrantLock lock = new ReentrantLock(); Condition notempty = new Condition(); Condition notfull = new Condition(); private Object[] buf; private int in = 0; //index for put private int out = 0; //index for get private int count = 0; //no of items private int size; Buffer(int size) { this.size = size; buf = new Object[size]; public void put(object o) {... public Object get() {... Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 28 / 1
Solution using Class Monitor public void put(object o) throws InterruptedException { lock.lock(); if (count >= size) notfull.await(); buf[in] = o; ++count; in = (in + 1) % size; notempty.signal(); lock.unlock(); public Object get() throws InterruptedException { lock.lock(); if (count == 0) notempty.await(); Object o = buf[out]; buf[out] = null; // display purposes --count; out = (out + 1) % size; notfull.signal(); lock.unlock(); return (o); Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 29 / 1
Review Mutual Exclusion Monitors vs Semaphores Java Monitors Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 30 / 1
Next Class Foster s design methodology partitioning communication agglomeration mapping Application Examples Boundary value problem Finding the maximum n-body problem Monteiro, Costa (DEI / IST) Parallel and Distributed Computing 10 2010-10-19 31 / 1