19 Do You Know the Different Types of Locks and Their Characteristics

19 Do You Know the Different Types of Locks and Their Characteristics #

In this lesson, we will first have a general understanding of the classification of locks and learn about the different criteria used for classifying locks. Then, in the following lessons, we will provide detailed explanations of the important types of locks.

7 Categories of Locks #

Firstly, it should be pointed out that these diverse categories are multiple criteria for evaluating something. For example, when evaluating a city, the criteria may include population size, economic development, and urban area size. A city may meet multiple criteria at the same time. For example, Beijing has a large population, developed economy, and a large urban area.

Similarly, for locks in Java, a lock may satisfy multiple criteria and fit into multiple categories. For example, ReentrantLock can be both an interruptible lock and a reentrant lock.

Based on the classification criteria, locks can be divided into the following 7 categories:

  • Biased Lock/Lightweight Lock/Heavyweight Lock;
  • Reentrant Lock/Non-Reentrant Lock;
  • Shared Lock/Exclusive Lock;
  • Fair Lock/Unfair Lock;
  • Pessimistic Lock/Optimistic Lock;
  • Spin Lock/Non-Spin Lock;
  • Interruptible Lock/Non-Interruptible Lock.

These are common classification criteria, and we will now introduce each of them in detail.

Biased Lock/Lightweight Lock/Heavyweight Lock #

The first classification refers to the state of the synchronized lock, and it is indicated by the mark word in the object header.

  • Biased Lock

If there is no contention for the lock from the beginning to the end, there is actually no need to acquire the lock. It only needs to be marked. This is the idea behind biased locks. When an object is initialized and no thread comes to acquire its lock, it becomes biased. When the first thread tries to access it and acquire the lock, the thread is recorded as the owner of the biased lock. In the future, if the thread trying to acquire the lock is the owner of the biased lock, it can directly obtain the lock with very low overhead and best performance.

  • Lightweight Lock

JVM developers have found that in many cases, the code in synchronized block is executed by multiple threads in an alternating manner, rather than simultaneously. This means that there is no actual contention or there is only short-time lock contention, which can be solved by CAS (Compare and Swap) without the need for a fully mutual heavyweight lock. A lightweight lock refers to the situation where a lock was originally biased, but it is accessed by another thread, indicating that there is contention. In this case, the biased lock will be upgraded to a lightweight lock. The thread will try to acquire the lock through spinning without blocking.

  • Heavyweight Lock

The heavyweight lock is a mutex lock, and it is implemented using the synchronization mechanism of the operating system, so it has relatively high overhead. When multiple threads have actual contention and the lock contention time is long, the lightweight lock cannot meet the requirements, so the lock will be escalated to a heavyweight lock. The heavyweight lock will cause other threads that cannot acquire the lock to enter a blocking state.

img

You can find the lock upgrade path: None → Biased Lock → Lightweight Lock → Heavyweight Lock.

To sum up, biased locks have the best performance as they can avoid performing CAS operations. Lightweight locks utilize spinning and CAS to avoid the thread blocking and waking caused by heavyweight locks, resulting in moderate performance. Heavyweight locks will block threads that cannot acquire the lock, resulting in the worst performance.

Reentrant Lock/Non-Reentrant Lock #

The second category is reentrant locks and non-reentrant locks. A reentrant lock refers to a situation where a thread already holds the lock and can acquire the lock again without releasing it. Similarly, a non-reentrant lock refers to a situation where even though a thread currently holds the lock, it must release it before attempting to acquire the lock again.

The most typical example of a reentrant lock is ReentrantLock, as the name suggests. “Reentrant” means it is reentrant, and it is also the primary implementation class of the Lock interface.

Shared Lock / Exclusive Lock #

The third classification criterion is shared lock and exclusive lock. A shared lock means that the same lock can be acquired by multiple threads at the same time, while an exclusive lock means that the lock can only be acquired by one thread at a time. Our read-write lock best illustrates the concept of shared lock and exclusive lock. The read lock in a read-write lock is a shared lock, while the write lock is an exclusive lock. The read lock can be read simultaneously and can be held by multiple threads at the same time, while the write lock can only be held by one thread at a time at most.

Fair Lock / Unfair Lock #

The fourth classification is fair lock and unfair lock. The fairness of a fair lock means that if a thread cannot acquire the lock at present, all threads will enter a waiting state and line up in a waiting queue. The thread that has been waiting for a longer time in the waiting queue will be given priority to acquire the lock, implying a “first-come, first-served” principle. On the other hand, an unfair lock is not as “perfect.” It may, under certain circumstances, ignore the threads already in the queue and allow cutting in line.

Pessimistic Lock/Optimistic Lock #

The fifth category is the pessimistic lock and its corresponding optimistic lock. The concept of a pessimistic lock is that before obtaining a resource, one must first acquire a lock in order to achieve an “exclusive” state. While the current thread is operating on the resource, other threads cannot affect it because they cannot acquire the lock. On the other hand, the optimistic lock is quite the opposite. It does not require acquiring a lock before obtaining a resource, nor does it lock the resource. Instead, the optimistic lock utilizes the concept of Compare and Swap (CAS) to modify the resource without exclusive access to it.

Spinlock/Non-spinlock #

The 6th classification is spinlock and non-spinlock. The idea behind spinlock is that if a thread cannot acquire the lock at the moment, it does not immediately enter a blocking state or release CPU resources. Instead, it starts a loop, continuously trying to acquire the lock. This looping process is metaphorically referred to as “spinning,” as if the thread is “self-rotating.” In contrast, the idea behind non-spinlock is that there is no spinning process. If the lock cannot be acquired, it is directly abandoned or other processing logic is performed, such as queuing or entering a blocking state.

Interruptible Lock/Non-Interruptible Lock #

The seventh classification is interruptible lock and non-interruptible lock. In Java, a lock decorated with the synchronized keyword represents a non-interruptible lock. Once a thread acquires the lock, there is no turning back and it can only proceed with other logical operations after obtaining the lock. On the other hand, our ReentrantLock is a typical interruptible lock. For example, when using the lockInterruptibly method to acquire the lock, if suddenly the thread no longer wants to acquire it, it can do other things after being interrupted, without having to wait foolishly until the lock is obtained before leaving.