Q & A of Java Concurrency and Multithreading

1. synchronized vs ReentrantLock

synchronized ReentrantLock
A key word A class
Automatically lock/unlock Manually lock/unlock
A key word A class
Automatically lock / unlock Manually lock / unlock
A key word A class
Provided by Java Language Provided by Java API
JVM level API level
unfair unfair / fair
Applied on objects, whose head saves the info of locks The states of locks is indicated by a int state identifier

2. Types of locking in HotSpot

  • Fat: JVM relies on OS mutexes to acquire lock.
  • Thin: JVM is using CAS algorithm.
  • Biased: CAS is rather expensive operation on some of the architecture. Biased locking - is special type of locking optimized for scenario when only one thread is working on object.
  • By default JVM uses thin locking.
    Later if JVM determines that there is no contention, thin locking is converted to biased locking.
    Operation that changes type of the lock is rather expensive, hence JVM does not apply this optimization immediately. There is a special JVM option - XX:BiasedLockingStartupDelay=delay which tells JVM when this kind of optimization should be applied.
  • Once biased, that thread can subsequently lock and unlock the object without resorting to expensive atomic instructions.
  • If biased, the single threaded code with locking and without locking has average same performance.

3. Countdownlatch vs Semaphore

They serve different purposes.

  • Use Semaphore to control thread access to resource.
  • Use CountDownLatch to wait for completion of all threads.

Semaphore definition from Javadocs:

A Semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer.

However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.

How does it work?

Semaphores are used to control the number of concurrent threads that are using a resource.That resource can be something like a shared data, or a block of code (critical section) or any file.
The count on a Semaphore can go up and down as different threads call acquire() and release(). But at any point of time, you can't have more number of threads greater than Semaphore count.

Semaphore Use cases:

  • Limiting concurrent access to disk (as performance degrades due to competing disk seeks)
  • Thread creation limiting
  • JDBC connection pooling / limiting
  • Network connection throttling
  • Throttling CPU or memory intensive tasks

CountDownLatch definition from Javadocs:

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

How does it work?

  • CountDownLatch works by having a counter initialized with number of threads, which is decremented each time a thread completes its execution.
  • When count reaches to zero, it means all threads have completed their execution, and thread waiting on latch resume the execution.

CountDownLatch Use cases:

  • Achieving Maximum Parallelism:
    Sometimes we want to start a number of threads at the same time to achieve maximum parallelism
  • Wait N threads to completes before start execution
  • Deadlock detection.