/ Java  

Java Multithreading 14: Lock

According to the time when the lock is added to Java, the lock in Java can be divided into synchronization lock and lock in the JUC package.

Synchronization lock

Using synchronized keyword to achieve the lock of mutually exclusive access to competing resources. Java 1.0 version already supports synchronous lock.

The principle of synchronous lock is that for each object, there is only one synchronous lock. Different threads can access the synchronous lock together. However, at the same point in time, the synchronization lock can only be acquired by one thread. In this way, the thread that has acquired the synchronization lock can perform CPU scheduling to execute. The thread that has not acquired the synchronization lock must wait until the synchronization lock is acquired before it can continue to run.

Lock in the JUC package

Compared with synchronous lock, the lock in the JUC (java.util.concurrent) package is more powerful. It provides a framework for locks. The framework allows more flexible use of locks, but its usage is more difficult.

The locks in the JUC package include: Lock interface, ReadWriteLock interface, LockSupport blocking primitive, Condition condition, AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer abstract classes, ReentrantLock exclusive lock, ReentrantReadWriteLock read-write lock.



Lock interface

The Lock interfacesupports lock rules with different semantics (reentrance, fairness, etc.). The so-called semantic difference means that the lock is fair mechanism lock, unfair mechanism lock, reentrant lock and so on.

  • Fair mechanism means the mechanism by which different threads acquire locks is fair
  • Unfair mechanism means the mechanism by which different threads acquire locks is unfair
  • Reentrant lock means that the same lock can be acquired multiple times by one thread.

ReadWriteLock

The ReadWriteLock interface defines some locks that readers can share and writers own in a similar way to Lock. There is only one class in the JUC package that implements this interface: ReentrantReadWriteLock, because it applies to most standard usage contexts. But programmers can create their own implementations that are suitable for non-standard requirements.

AbstractOwnableSynchronizer

AbstractQueuedSynchronizer

AbstractQueuedLongSynchronizer

AbstractQueuedSynchronizer is a class called AQS, which is a very useful superclass that can be used to define locks and other synchronizers that rely on queued blocked threads. ReentrantLock, ReentrantReadWriteLock, CountDownLatch, CyclicBarrier, and Semaphore are all based on AQS implementation. The AbstractQueuedLongSynchronizer class provides the same functionality but extends 64-bit support for synchronization status. Both class extend the class AbstractOwnableSynchronizer (a simple class that helps record threads that are currently maintaining exclusive synchronization).

LockSupport

The function of LockSupport is similar to Thread.suspend() and Thread.resume(). The functions of park() and unpark() in LockSupport are to block and unblock threads, respectively. However, park() and unpark() will not encounter the deadlock problem caused by Thread.suspend() and Thread.resume().

Condition

Condition needs to be used in conjunction with Lock. It’s role is to replace the Object monitor method, you can sleep/wake up the thread through await() and signal()

ReentrantLock

ReentrantLock is an exclusive lock. The so-called exclusive lock means a lock can only be occupied by only one thread. ReentrantLock lock includes fair ReentrantLock and unfair ReentrantLock.

  • Fair ReentrantLock means the mechanism by which different threads acquire locks is fair
  • Unfair ReentrantLock means the mechanism by which different threads acquire locks is unfair

ReentrantLock is a reentrant lock.



  • ReentrantLock implements the Lock interface
  • There is a member variable sync in ReentrantLock. sync is Sync type. Sync is an abstract class, and it inherits from AQS
  • ReentrantLock includes FairSync and NonfairSync, which are all subclasses of Sync The sync object in ReentrantReadWriteLock is one of FairSync and NonfairSync, which also means that ReentrantLock is one of fair lock or unfair lock. ReentrantLock is a non-fair lock by default

ReentrantReadWriteLock

ReentrantReadWriteLock is the implementation class of ReadWriteLock, which includes the subclasses ReadLock and WriteLock. ReentrantLock is a shared lock, and WriteLock is an exclusive lock.



  • ReentrantReadWriteLock implements the ReadWriteLock interface
  • ReentrantReadWriteLock contains sync objects, reader lock readerLock and write lock writerLock. Both ReadLock and WriteLock implement the Lock interface
  • Like ReentrantLock, sync is a Sync type. Moreover, Sync is also an abstract class inherited from AQS. Sync also includes FairSync and NonfairSync

CountDownLatch

CountDownLatch is a synchronization helper class that allows one or more threads to wait until it completes a set of operations being performed in other threads.



CountDownLatch contains sync object, sync is Sync type. Sync of CountDownLatch is an instance class, which inherits from AQS.

CyclicBarrier

CyclicBarrier is a synchronization helper class that allows a group of threads to wait for each other until they reach a common barrier point. Because the barrier can be reused after releasing the waiting thread, it is called a circular barrier.



CyclicBarrier contains ReentrantLock object lock and Condition object trip, it is implemented by exclusive lock.

The difference between CyclicBarrier and CountDownLatch is:

  • CountDownLatch is to allow 1 or N threads to wait for other threads to finish execution, while CyclicBarrier is to allow N threads to wait for each other.
  • The counter of CountDownLatch cannot be reset. The counter of CyclicBarrier can be used after being reset, so it is called a cyclic barrier.

Semaphore

Semaphore is a counting semaphore, its essence is a shared lock.

Semaphore maintains a semaphore permission set. A thread can obtain permission for a semaphore by calling acquire(). When a permission is available in the semaphore, the thread can obtain the permission. Otherwise the thread must wait until a permission is available. The thread can release the semaphore license it holds through release().



Like ReentrantLock, Semaphore contains sync objects, sync is of type Sync. Moreover, Sync is also an abstract class inherited from AQS. Sync also includes fair semaphore FairSync and unfair semaphore NonfairSync.