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
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
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.
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
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
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.
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 }
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
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.
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
{ 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.
{ // 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.
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
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.
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
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.
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.