Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java Concurrency. Ottawa JUG meetup. 2018-02-08.

Java Concurrency. Ottawa JUG meetup. 2018-02-08.

Aleksey Vorobyov

February 08, 2018
Tweet

More Decks by Aleksey Vorobyov

Other Decks in Technology

Transcript

  1. X things a Developer should know about Java concurrency Aleksey

    Vorobyov Ottawa JUG, February 8th, 2018
  2. Concurrency and Parallelism • Concurrency is the composition (design) of

    independently executing processes • Parallelism is the simultaneous execution of (possibly related) computations. • Concurrency is about dealing with lots of things at once. • Parallelism is about doing lots of things at once. • Concurrent blocks can be run in parallel
  3. How much we can get from parallelism Amdahl’s Law formula

    gives the theoretical speedup in latency of the execution of a task at fixed workload Real speedup is less.
  4. Hardware Memory Model basics • CPU executes code in one

    of its cores • CPU loads data from RAM to core caches and registers • CPU modifies data in registers and caches and periodically synchronize it with RAM
  5. Memory Access Latency Access Latency Comment L1 cache reference 0.5

    ns Branch mispredict 5 ns L2 cache reference 7 ns 14x L1 cache Mutex lock/unlock 25 ns Main memory reference 100 ns 20x L2 cache, 200x L1 cache
  6. Java Memory Model basics • Each thread has its own

    stack • Local primitive variables are allocated in a stack • All objects are allocated in a heap • Shared objects in a heap
  7. Multithreading is not free • System becomes more complex •

    Requires more resources • context switching • ~2 MB per local stack per thread
  8. Program Order is not a real Execution Order // Program

    order in a code x.a = 1 x.b = 2 // Valid execution order in CPU x.b = 2 x.a = 1 Source Code -> [Java Compiler] -> Byte Code -> [JIT Compiler] -> Native Code -> [CPU] Each transformation can apply optimizations It’s not a problem for single thread.
  9. Shared object visibility example // Thread 1 x.a = 1

    x.b = 2 // Thread 2 t1 = x.a t2 = x.b // (t1, t2)? a. (1, 2) b. (0, 0) c. (1, 0) d. (0, 2)
  10. 'volatile' guaranty visibility • Read from RAM • Write to

    RAM (* all shared objects since 1.5) • Thread is not blocked • Apply happens-before restriction • Volatile is enough • If only one and the same thread writes to it, and all other threads only read it • Writes to a variable do not depend on it current state
  11. Visibility summary • The value of a final variable is

    visible after initialization. • The initial value of a static variable is visible after static initialization. • Changes to a volatile variable are visible. • Changes that happen before releasing a lock are visible to anyone acquiring the same lock
  12. Race conditions • Race conditions can be avoided by •

    proper thread synchronization in critical sections; • Atomic types; • Immutable objects; public class Counter { private volatile long count = 0; public void add(long value) { this.count = this.count + value; // is not atomic } }
  13. Synchronized methods and blocks • Synchronized can be applied on

    a method or a field(block) • Can be static (class-level) or non-static (object/field level) • Synchronized is reentrant • Synchronized is relatively cheap for business applications STATE DESCRIPTION init Just created, never acquired. biased There is no contention and the code protected by the lock is executed only by one thread. The cheapest one to acquire. thin Monitor is acquired by several threads with no contention. Relatively cheap CAS is used for taking the lock. fat There is contention. The JVM requests an OS mutex and lets the OS scheduler handle thread-parking and wake ups.
  14. Field as a lock best practices • Lock field should

    be final • String is bad candidate for a lock field. Strings are stored in a common pool and are immutable. The same string constant can be used as a lock by mistake. private final Object lock = new Object(); synchronized(lock) { // do something }
  15. Atomic • Atomic types in java.util.concurrent.atomic package, e.g. AtomicInteger •

    Adder types e.g. LongAdder • Addition is cheap, but getting an accumulated value is expensive • Atomic CAS operations work on a hardware level and don’t use expensive Java synchronization monitors • Atomic CAS do not block a thread
  16. Immutable objects 1. Be sure to declare instance variables final.

    The VM ensures that a final instance variable is visible after construction. 2. None of the methods can be mutators. You may want to make them final, or declare the class final, so that methods can’t be overridden with mutators. 3. Don’t leak mutable state. None of your (non-private) methods can return a reference to any innards that could be used for mutation. 4. Don’t let the this reference escape in a constructor.
  17. Liveness • Deadlock • two or more threads are blocked

    forever, waiting for each other • Solution: lock in the same order • Livelock • threads spend all of their time negotiating access to a resource or detecting and avoiding deadlock such that no thread actually makes progress • Thread starvation • a thread is unable to gain regular access to shared resources and is unable to make progress
  18. How to interrupt a thread? Runnable task = () ->

    { try { while (more work to do) { // Do work Thread.sleep(millis); } } catch (InterruptedException ex) { // Do something Thread.currentThread().interrupt(); // throw a more detailed exception } }; Runnable task = () -> { while (more work to do) { if (Thread.currentThread().isInterrupted()) return; //Do work } }; In Java thread interruption is a cooperative effort. Someone has to ask a thread to interrupt. The thread should react on this cancelation request. Thread::interrupt() Never swallow an interruption request.
  19. JVM shutdown hook Runtime.getRuntime().addShutdownHook( new Thread() { public void run()

    { // do something // This is a final chance to cleanup system resources } }); When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently.
  20. ReentrantLock • is similar to synchronized • lock/unlock, tryLock with

    a timeout • isLocked • Can be fair or unfair • provides some runtime information about itself like a thread that owns it
  21. ReadWriteLock • Allows multiple concurrent readers (non-exclusive locks), but only

    one writer (exclusive lock) • Write lock can be downgraded to a read lock • Can be fair or unfair
  22. StampedLock • Allows to use optimistic locking • When we

    try to acquire an optimistic read lock Java doesn't block us even if another thread owns a write lock. • NOT reentrant
  23. Semaphore • restricts the number of threads than can access

    some (physical or logical) resource • Construct a semaphore with a desired number • A thread calls acquire() then release() • If a specified number of acquisitions is reached then acquire() call is blocked
  24. CountDownLatch • A synchronization aid that allows one or more

    threads to wait until a set of operations being performed in other threads completes. • One-time only. Can’t be reused. Used usually in initializations.
  25. CountDownLatch • How to use • Create CountDownLatch with a

    desired number • In ‘waiter’ threads call await() method. Thread is blocked after that. • In ‘decrementer’ threads call countDown() • When latch reaches 0 then ‘waiter’ threads are unblocked
  26. CyclicBarrier • A synchronization aid that allows a set of

    threads to all wait for each other to reach a common barrier point. • Can be reused many times after calling reset() method • How to use • Create CyclicBarrier with a desired number N • In call await() in participated threads. Threads are blocked after that. • As soon as await() is called N times, all threads are unblocked.
  27. Phaser • The Phaser is a barrier on which the

    dynamic number of threads need to wait before continuing execution. • Can register and deregister threads • Can be reset • For very advances use cases
  28. Exchanger • A synchronization point at which threads can pair

    and swap elements within pairs. • V excange(V x) method waits for another thread to arrive at this exchange point and then transfers the given object to it, receiving its object in return.