90 likes | 253 Views
Condition Variables and Producer/Consumer. CSE451 Andrew Whitaker. Background. Often, a thread needs to wait on another thread until some condition becomes true Example: producer/consumer problems Some threads produce items Other threads consume items
E N D
Condition Variablesand Producer/Consumer CSE451 Andrew Whitaker
Background • Often, a thread needs to wait on another thread until some condition becomes true • Example: producer/consumer problems • Some threads produce items • Other threads consume items • Consuming threads block until there is something to consume • Condition variables provide a “rendezvous” mechanism • Wait until some condition becomes true
A Simple Example • Thread 1: • Wait a second • Increment a counter • Repeat • Thread 2: • Wait for the counter to reach 10 • (in other words, wait ten seconds)
Busy waiting is bad! publicclass TimerCounter implements Runnable { // this counter gets incremented every second staticvolatileint count = 0; staticfinalint TARGET = 10; publicstaticvoid main(String[] args) { // start the counter thread Thread t = new Thread (new TimerCounter()); t.start(); // wait TARGET seconds while (count < TARGET) { ; } // busy wait System.out.println(TARGET + " seconds has expired"); } publicvoid run() { while (count < TARGET) { try { Thread.sleep(1000); // sleep for one second } catch (InterruptedException e) {} // ignored count++; } } }
Revised Version • Replace busy waiting with a condition variable • Allows the thread to safely give up the processor • Essentially, we are replacing polling with interruption
wait releases the lock // class TimerCounter { staticfinal Object lockObject = new Object(); publicstaticvoid main(String[] args) { // initialization as before synchronized (lockObject) { while (count < TARGET) { try { lockObject.wait(); } catch (InterruptedException excp) {} // ignored } } System.out.println(TARGET + " seconds has expired"); } publicvoid run() { while (count < TARGET) { try { Thread.sleep(1000); } // sleep for one second catch (InterruptedException e) {} // ignored count++; } synchronized (lockObject) { lockObject.notify(); } } }
Condition Variable Details • Condition variables support three operations: wait,notify,notifyAll • Every condition variable is associated with a lock • The lock mustbe held when doing any operation • Invoking wait releases the lock • Lock is held when wait returns • Condition predicate should always be tested in a while loop
Under the Covers • Each condition variable has an associated wait queue • Lock ensures thread-safe access to this queue • notify: Move one thread from blocked to runnable • notifyAll: Move all threads from blocked to runnable blocked threads
Example: Bounded Buffer • Bounded buffer is a finite queue of elements • Commonly used to coordinate producers and consumers • Put adds an element to the queue • And, blocks if the queue is full • Take removes an element from the queue • And, blocks if the queue is empty put take