Java concurrency beyond basisc D Irtegov Novosibirs State
Java concurrency beyond basisc D. Irtegov Novosibirs State University 2020
Thread. Local • java. lang. Thread. Local<T> • used with variables that can only be accessed (read and write) by the same thread public class Example. Thread. Local { public static class Example. Runnable implements Runnable { private Thread. Local<Integer> thread. Local = new Thread. Local<Integer>(); @Override public void run() { thread. Local. set((int) (Math. random() * 500)); System. out. println("Thread Local Variable Value : " + thread. Local. get()); } } public static void main(String[] args) { Example. Runnable runnable = new Example. Runnable(); Thread t 1 = new Thread(runnable); Thread t 2 = new Thread(runnable); t 1. start(); t 2. start(); } }
Advanced synchronization primitives • Found under java. util. concurrent • High level concurrency objects • • • Locks Semaphores Barriers Future Concurrent Collections Atomic variables
Locks • Lock class • lock() • unlock() • Reentrant. Lock • Read. Write. Lock
Semaphore • Dijkstra semaphore or counting semaphore • Semaphore(int permits) - set initial value of the flag variable • acquire() or acquire(int) – decrease flag variable by 1 or param, block if flag variable would become < 0 • release() or release(int) - increase flag variable by 1 or param, wake threads waiting in acquire(), if any • Utility methods: available. Permits(), get. Queue. Length(), try. Acquire()
Barrier • Cyclic. Barrier(int parties) • await() – blocks until parties threads call await() • reset() – engage the barrier again • Used mostly to synchronize long computations, so one thread would not run too long ahead of others • Count. Down. Latch, Phaser
Future • Future<V> - interface to asynchronously create the value of type V. • get() – get the value, block until available or cancelled • Cancellable • Future. Task(Callable<V> callable) - callable must return value to get() • Future. Task(Runnable runnable, V result) – runnable must call set()
Concurrent collections • Try to implement fine-grained locking instead of just wrapping add/get methods in sync block • Weakly consistent iterators • may proceed concurrently with other operations • never throw Concurrent. Modification. Exception • guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect modifications subsequent to construction.
Common multithreading gotchas • • Deadlocks and livelocks Starvation Busy waits or spin waits (use wait/notify instead!) Poor scalability, typically due to coarse locking Incorrect fine-grained locking Critical sections spanning method boundaries Creating too many threads • if you have more threads than CPU cores/hardware threads, it’s time to rethink the architecture • Using API that are not thread-safe or have known gotchas
Deadlock // Thread 1 synchronized(lock 1) { synchronized(lock 2) { // stuff } } // Thread 2 synchronized(lock 2) { synchronized(lock 1) { // stuff } }
How to avoid • Lock ordering • If your application has layered structure, might occur naturally • Be careful when subclassing lock-holding classes! • Using try. Lock or timeouts – bad idea, • can lead to livelocks (busy wait in try. Lock) • When you suspect a deadlock, you need to release all locks • In Java, you can throw exception, but you need to know where to catch it • Java has no facilities for group locks or runtime deadlock checking • These methods got out of fashion in 90 s, and there are reasons for this • Group locks are not really compatible with encapsulation and code reuse • Runtime checks provoke livelocks
Starvation • If you use lock ordering to avoid deadlocks outermost locks are acquired early and held for long time • Threads that need outermost locks might get in trouble • Avoid deep nested locks • Easier to say than to do… • In read/write locks, the write lock also can starvate
Busy wait • Probably the single worst crime in asynchronous programming • Not just multithreading, but also in I/O and network • When you busy wait, you consume CPU and prevent other threads from working • When you consume CPU, you consume power (think about battery or datacenter cooling budget or cloud tariffs) • Sleep wait also is considered harmful • Use wait/notify or Future or … • What if the event source does not call notify? • What if, on the network, notify message is lost?
- Slides: 13