Intro To Java Week 4 Wednesday, November 19, 14
Homework Review Week 1 Hadamard Week 2 Rational, Complex, Stack, CSV Wednesday, November 19, 14
Recap Generics Can’ t be used with primitives(but can use wrapper objects) Collections Use generics extensively Key interfaces: Collection, Set, List, Map Key implementations: HashSet, HashMap, ArrayList Wednesday, November 19, 14
Why Concurrency? People expect and demand it iTunes, OSes, web servers Multi-server, single queue Performance gains, exploit concurrent hardware Reliability - a thread can die, w/o killing entire prog Some tasks are inherently “concurrent” Robot walking in real time Networking Developers sometimes forced by use of a package to deal with concurrency - like a GUI Wednesday, November 19, 14
In General, Concurrency Is Difficult!! Like memory management, complex schemes are very difficult to get right and debug Systems can run fine for a year yet still be broken - time bombs We will survey some of the issues, but do not expect to master anything Java concurrency tools are excellent - there are lots of things can be built w/o expertise Wednesday, November 19, 14
Concurrency In Hardware Can get “appearance” of concurrency on single CPU by time slicing threads Multiple core CPUs now common. Can distribute threads across different cores Wednesday, November 19, 14
Deprecated In older code (pre 1.5), new Threads would be made by explicitly instantiating Thread objects, and perhaps calling “join” to wait for a Thread to terminate Thread, ThreadPool, Timer, TimerTask Executors provides thread pools and timer functionality wait(), notify(), notifyAll(), start(), stop(), resume() interrupts - just a flag, not like control-C Probably the only thing you want to use Thread for is Thread.sleep() Wednesday, November 19, 14
Processes vs Threads A “process” is provided by the OS. Heavyweight object, with isolated address space A “thread” is provided by the JVM. Lightweight object, shares address space with all other threads Generally IO is much slower than CPU, so having multiple threads reduces the amount of CPU idle time Threads can distribute to different “cores” on multi- core CPUs Wednesday, November 19, 14
java.util.concurrency Execution - manage thread lifecycle Synchronizers - coordinate groups of threads Locks - mutual exclusion synchronized statement Atomics - shared state w/o locks Fork/Join - divide and conquer Wednesday, November 19, 14
Resource Pools Normally “new” classes, use the objects for awhile, forget them, and the GC picks them up for us Some resources(represented by a class) are too expensive for this approach, so they are explicitly managed and recycled Wednesday, November 19, 14
Thread Pools Threads are expensive to make, start, and destroy. Don’ t want the extra latency Thread resources may not be freed for some time If you make a new thread for every task, can wind up with too many threads contending for system resources - very inefficient Better to size thread pool relative to hardware resources, and queue tasks if necessary Wednesday, November 19, 14
java.util.concurrent.Executors Big collection of static methods for making Executors of various types. Better than overloading constructor Executor manages a resource pool of threads Will replace a thread that dies Provides lifecycle tools like shutdown() Passes tasks to idle threads, and reclaims the thread when it finishes for the next task Wednesday, November 19, 14
java.lang.runnable An interface - a class implements it by providing method public void run() {...} Executor will supply a thread to execute the run method No value or errors are returned example: RUN Wednesday, November 19, 14
Callable and Future Callable<T> is a generic interface. class implements it by providing method public T call() throws Exception {...} Executor supplies a thread to compute call(), returns a Future<T> Future tracks the async progress of call() cancel(), if it has not already started get(), get the value returned by call(), or the error it threw example: callfut Wednesday, November 19, 14
Synchronizers Force threads to wait for various conditions to become true Constructors can NOT be synchronized - they are called by “new” Lock objects more flexible, but harder to use Wednesday, November 19, 14
Semaphore Classic concurrency primitive Starts with initial count of “permits” acquire() grabs a permit, if available. otherwise blocks until it can get one release() returns a permit Wednesday, November 19, 14
CountDownLatch Given an initial count Calling countDown() decrements the count Any number of calls to await() block until the count = 0 Not resetable example: CntDown Wednesday, November 19, 14
CyclicBarrier Given an initial count N await() calls will block until N threads have called it, then await() will return Optionally, a Runnable can be called when the Barrier is crossed Can be reused example: cb Wednesday, November 19, 14
ExecutorCompletionService Submit N Callable tasks As tasks complete, can pull futures off in completion order from a queue example: complete Wednesday, November 19, 14
Exchanger<T> Thread A calls an exchanger with a T1, and blocks Thread B calls the exchanger with a T2, and gets back T1, and Thread A gets back T2 Wednesday, November 19, 14
One Shot and Periodic Tasks Special Executor handles time based “Runnable” tasks example: scheduled If you need complex scheduling, including “cron” style specs, look at the 3rd party Quartz scheduler Wednesday, November 19, 14
Fork/Join Dynamic divide and conquer. keep subdividing a task until it is small enough to complete example: fj Wednesday, November 19, 14
example: contend Try synchronized, synchronized(this), synchronized(lock), atomic Wednesday, November 19, 14
example: contend Race problem btw the two threads - cnt++ is NOT atomic Try synchronized, synchronized(this), synchronized(lock) - 10X slower! atomic - 3X slower Wednesday, November 19, 14
Races Outcome depends on who crosses the finish line first. Code below is broken / / Want expensive to be a singleton class Foo() { static Expensive expensive; Expensive getExpensive() { if (null == expensive) expensive = new Expensive(); return expensive; } } Wednesday, November 19, 14
Eliminate the Race With a Lock Outcome depends on who crosses the finish line first / / Want expensive to be a singleton class Foo() { static Expensive expensive; synchronized Expensive getExpensive() { if (null == expensive) expensive = new Expensive(); return expensive; } } Wednesday, November 19, 14
Locks synchronized method - sets up a “mutex” (mutual exclusion, critical section, one thread at a time region) Locks are somewhat expensive - OS is involved, threads must be suspended and resumed, which involves context swapping Sounds alot like databases - ACID Atomic, Consistent, Isolated (but not Durable) STM - Software Transactional Memory Wednesday, November 19, 14
Three Types of Synchronized Statements / / ANY exit - normal, thrown error, releases the lock class Foo { / / Lock object is “Foo.class” (class literal). locks the method synchronized static void bar() { ... } / / Lock object is “this”, the instance itself. locks the method synchronized void zip() { ... } / / ANY object can be used as a lock Object lock = new Object(); void zap() { ... synchronized(lock) { / / this block is protected} ...} Wednesday, November 19, 14
How Bad Can It Get? 1 example: DL Wednesday, November 19, 14
Deadlocks Some can avoided by always requesting resources in the same order Bob & Larry are doing house repairs. They both need a hammer and a screwdriver Also known romantically as a “deadly embrace” Wednesday, November 19, 14
How Bad Can It Get? 2 Prog might print zero, or maybe never print at all! class Yikes implements Runnable{ static boolean ready; static int num; public void run() { while(!ready) sleep(briefly); System.out.println(num) } public static void main(String args[]){ executor.execute(new Yikes()); num = 42; ready = true; } Wednesday, November 19, 14
Instruction Reordering All kinds of sneaky things are going on behind your back for performance might change num = 42; ready = true ready=true; num =42 ok to do because executing thread can’ t tell the difference - but OTHER threads can!! Wednesday, November 19, 14
How Bad Can It Get? 3 Thread A sets up an instance of Yikes ThreadB calls Yikes.mustBeTrue() due to cache changes, method might return FALSE!! class Yikes { private int n; public Yikes(int n) { this.n = n; } public boolean mustBeTrue() { n == n } } Wednesday, November 19, 14
Independent Caches First and second read of n could fetch different values, depending on what happens with the caches Java Memory Model allows this, because if values were always “up to date” it would render the caches worthless Get huge speedups with caches - main memory is very slow Sometimes variables are in a CPU register - an even faster “cache” Wednesday, November 19, 14
Recommend
More recommend