Concurrency Quick Reference

A quick reference on concurrency and related concepts with Java specifics.


  • Concurrency vs parallelism:
  • Threads vs process (should be true for Unix too)
    • Lightweight, share address space vs heavyweight, do not share memory
  • Visibility: a change is visible in all threads
    • The memory model specifies when and how changes become visibleEffective
  • Atomicity: An operation acting on shared memory is atomic if it completes in a single step relative to other threads. When an atomic store is performed on a shared variable, no other thread can observe the modification half-complete. When an atomic load is performed on a shared variable, it reads the entire value as it appeared at a single moment in time. Non-atomic loads and stores do not make those guarantees.
    • In Java reads/writes to variable are atomic unless the variables are long or double. Use AtomicLong instead.
  • Optimistic vs pessimistic locking:
    • Optimistic: compare and swap, do the change and then amend if possible or discard
    • Pessimistic: lock first, then change (synchronised blocks etc)
  • Types of locks: intrinsic/implicit vs explicit
    • Based on how the lock object is specified
  • Semaphore vs mutexes: mutex is a binary semaphore (locked or unlocked) that can be accessed only by the thread that locked it.
  • Monitor vs Semaphore: monitor is like a public toilet, semaphore like a bike hire place.
  • Context switch: is the process of storing the state of a process or of a thread, so that it can be restored and execution resumed from the same point later.

Thread issues

From Epi:

  • Race conditions or thread interference: Interference happens when two operations, running in different threads, but acting on the same data, interleave. This means that the two operations consist of multiple steps, and the sequences of steps overlap.
  • Memory consistency: Memory consistency errors occur when different threads have inconsistent views of what should be the same data.
    • Has to do with visibility.
    • Mutability of data
  • Deadlock: when a thread is waiting a lock another thread has, while the other thread waits for a lock the first one has.
    • 4 conditions should be met (mutual exclusion, hold and wait, no preemption, circular wait)Ctci
  • Livelock (liveness failure in Effective): a processor keeps retrying an operation that fails
  • Starvation: a processor needs a resource but never gets it

Java specific

Running tasks simultaneously:

Thread safety on variables

  • volatile variables: The value of the variable will never be cached thread-locally: all reads and writes will go straight to "main memory". Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.source
    • Note 1: volatile ensures atomicity of double & longs writes and reads even though they (without volatile) happen in 2 operations.
    • Note 2: myVolatile++; is a compound action (get and set) therefore not thread safe using just volatile!
    • Static volatile variables make sense
  • AtomicReferenceFieldUpdater->VarHandles (in Java 9)
  • java.util.concurrent.atomic for AtomicInteger etc.
  • ThreadLocal is in a sense the opposite of volatile: each thread maintains a local

Locking (on code)

Locking in general guarantees both visibility and atomicity properties.

  1. Synchronization with synchronized
    • It's an intrinsic (or implicit or monitor) lock
    • It's re-entrant: the thread that already has the lock can re-enter the synchronized code (but not another thread).
    • Can be on a method (static or instance) or block of code. Difference?
    • Method ones have more overhead: they block all other synchronized methods i.e. if it's on an instance method all synchronized instance methods are blocked, if on a static all static ones are blocked. This ensures the visibility property: when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. Another resource
  2. Locks (e.g. mutex, semaphore: counting/binary) Lock, Semaphore
    • Explicit locks, provide more granular control and semantics.
    • Can be re-entrant or not and support various Conditions.
    • Can just attempt a lock: tryLock