preface

A lock, as the name implies, locks up resources that can only be operated when we get the key. In our Java, database, and distributed environments, there are always a variety of locks that are a headache, such as “fair locks”, “spin locks”, “read/write locks”, “distributed locks”, and so on.

In fact, there are not so many locks, many concepts are explained in terms of different features, design, and lock state, so we can figure out why there are these “locks” according to different categories. Sit tight and get ready to drive.

The body of the

“Fair Lock” and “Unfair Lock”

Fair lock: refers to the thread at the time of waiting to get the same lock, is in strict accordance with the application of lock time sequence, this means that the normal operation of the program, there will be no thread execution, and be “starved to death”, but also need an additional mechanism to maintain this order, so efficiency relative to the fair will be almost the lock.

Unfair lock: The concept is the opposite of “fair lock”, random thread to acquire the lock, relatively high phase rate.

new ReentrantLock(); // Default unfair lock
new ReentrantLock(true); / / fair lock
Copy the code

“Reentrant lock (Recursive lock)” and “Non-reentrant Lock (spin lock)”

Note that reentrant/recursion, non-reentrant/spin, is the same lock in terms of how it behaves and how it is implemented.

Reentrant lock: when A thread acquires an A lock, the current thread can also enter if subsequent methods are locked by the A lock.

public class Demo {
  private Lock lockA;
 
  public Demo(Lock Lock) {
    this.lockA = lock;
  }
 
  public void methodA(a) {
    lockA.lock();
    methodB();
    lockA.unlock();
  }
 
  public void methodB(a) {
    lockA.lock();
    //dosmlockA.unlock(); }}Copy the code

When we run methodA(), the thread gets the lockA, and when we call methodB(), we find that the lockA is also needed. Since this is a reentrant lock, the current thread can also enter it directly. Synchronized and ReetrantLock are both reentrant locks in Java.

Unreentranceable lock: When methodA accesses methodB, it is not possible to obtain the lock directly. UnLock must be called first. So what’s the way to implement a non-reentrant lock? That’s spin, so there’s a nickname for spin locks.

public class SpinLock {

  private AtomicReference<Thread> sign =new AtomicReference<>();

  public void lock(a){
    Thread current = Thread.currentThread();
    while(! sign .compareAndSet(null, current)){
    }
  }

  public void unlock (a){
    Thread current = Thread.currentThread();
    sign .compareAndSet(current, null); }}Copy the code

The “Pessimism Lock” and the “Optimism Lock”

These two types of locks, in fact, are a very macro classification, it is not a specific lock, but a general view of the degree of concurrency.

Pessimistic lock: there is a “pessimistic” mentality, since every time you take data, you will think that the data will be modified, so you must add a lock to ease.

Optimistic locking: Optimistic children who believe that the same data will not be concurrent operations, so they will not lock the data, only when the update, such as the version number to determine whether the data has been changed.

In Fact, all kinds of locks in Java are the implementation of pessimistic locks. Both the operation data will be locked by the thread that obtains the lock, while optimistic locks are generally realized through the idea of CAS (Compare and swap). For example, some atomic classes AtomicInteger use spin to update atoms.

“Shared Locks” and “Exclusive Locks”

The concepts of these two locks are more common in database transactions.

Shared lock: also called read lock or S lock. If A transaction locks data A with A shared lock, other transactions can only lock data A with A shared lock, not an exclusive lock. Transactions that are allowed to share locks can only read data, not modify it. The same is true for ReetrantReadWriteLock() in Java.

Exclusive lock: also called exclusive lock, write lock, or X lock. If A transaction locks data A exclusively, other transactions cannot lock data A of any type. A transaction that acquires an exclusive lock can both read and modify data.

A distributed lock

The locks we talked about above are realized between different threads of a single program. When different programs need to compete for the same resource, distributed locks are needed. We can realize distributed locks through redis, ZooKeeper and other middleware.

For locks, there are biased locking, lightweight lock, etc., but it involves the content is more, there would not be in open space is introduced, interested students can study, if you can understand the above introduction of these locks, it basically in the vast majority of the company about the “lock” problem can be solved.