- Concurrency (cont.) Today: Concurrency in Java Consistency issues on multiprocessors First, monitors - start with locks, as before - add "condition variables" (in Java, they're the same thing) Condition variables - supported calls: wait(), notify(), notifyAll() - one thread calls wait() - implicitly, all locks being held are freed - another thread calls notify() - places exactly one wait()ing thread back on the run queue - locks implicitly reacquired in original order - notifyAll() places *all* waiting thread back on run queue How all this works in Java - Every object has a lock built into it - Every class has one as well - synchronized keyword on method -- acquires instance lock - synchronized keyword on static -- acquires class lock - can add new locks (just get yourself a new Object) - synchronized(any_object) { code block } - How to create a new thread? - starting a thread: childThread = new Thread(new Runnable { public void run() { ... } }); childThread.start(); - waiting for a thread to die: childThread.join(); - yielding Thread.currentThread().yield(); - Footnote: early versions of Java used non-pre-emptive threads, but current versions all have pre-emption. yield() is a way to be polite, but it's not required. - Last time, remember we had read-locks and write-locks? - Java style is typically to just use the class lock - wait() when somebody's going to change the state - notifyAll() when a change is made - put wait() into an infinite loop - implementing a producer/consumer style buffer class Buffer { private Object storage; synchronized void store(Object x) { while(storage != null) wait(); storage = x; notifyAll(); } synchronized Object get() { while(storage == null) wait(); Object tmp = storage; storage = null; notifyAll(); return tmp; } } - exercises for the reader - increasing the storage space (allows for more concurrency) - separate read and write locks (allows for fewer people waking up each time) - Ugly issue: write consistency - Digression: how memory works in multi-processor machines - Cache hierarchy - Delayed write propagation to RAM - Write ordering, etc. - Java spec says: - No guarantees without locks - Anything or nothing could happen - After *any* lock is released, *all* changes propagate immediately - Note: *many* different kinds of consistency models (different on different kinds of multiprocessors, distributed clusters, etc.) - Paranoia: use locks and you'll be fine - A concrete problem: implementing a "Stop" button - use "volatile" boolean - "volatile" guarantees that write are immediately visible everywhere - CPU-thread is doing some "real" work - GUI-thread receives button click, sets boolean to true - CPU-thread occasionally reads boolean, sets to false ==> no locking required