An introduction to blocking locks and code examples of Java locks

  • 2020-04-01 03:27:44
  • OfStack

As a tool for concurrent sharing of data and ensuring consistency, locks are implemented in the JAVA platform in various ways (such as synchronized, ReentrantLock, and so on). These locks have been written and provided to facilitate our development, but the specific nature and type of locks are rarely mentioned. This series of articles will examine common lock names and features in JAVA to answer your questions.

Blocking locks

Blocking locks, unlike spin locks, change the running state of a thread.
In a JAVA environment, a Thread has the following states:

1, new state

2. Ready state

3. Running state

4. Blocking state

5. State of death

Blocking lock, can be said to let the thread into the blocking state to wait, when the corresponding signal (wake, time), can enter the ready state of the thread, ready to all threads, through competition, into the running state.

Methods that can enter a \ exit, blocking state, or contain blocking locks in JAVA are the synchronized keyword (where the weight lock is), ReentrantLock, object.wait ()\notify(), locksupport.park ()/unpart()(often used by J.U.C)

Here is a JAVA blocking lock instance:


package lock;

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.LockSupport;

public class CLHLock1 {
  public static class CLHNode {
    private volatile Thread isLocked;
  }

  @SuppressWarnings("unused")
  private volatile CLHNode                      tail;
  private static final ThreadLocal<CLHNode>              LOCAL  = new ThreadLocal<CLHNode>();
  private static final AtomicReferenceFieldUpdater<CLHLock1, CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock1.class,
                                          CLHNode.class, "tail");

  public void lock() {
    CLHNode node = new CLHNode();
    LOCAL.set(node);
    CLHNode preNode = UPDATER.getAndSet(this, node);
    if (preNode != null) {
      preNode.isLocked = Thread.currentThread();
      LockSupport.park(this);
      preNode = null;
      LOCAL.set(node);
    }
  }

  public void unlock() {
    CLHNode node = LOCAL.get();
    if (!UPDATER.compareAndSet(this, node, null)) {
      System.out.println("unlockt" + node.isLocked.getName());
      LockSupport.unpark(node.isLocked);
    }
    node = null;
  }
}

Here we use the blocking lock for locksupport.unpark (). This example is a modification of the CLH lock.

The advantage of blocking locks is that the blocked thread does not consume CPU time, resulting in excessive CPU usage, but both entry time and recovery time are slightly slower than spin locks.

The performance of blocking lock is higher than that of spin lock under the condition of intense competition.

The ideal is; In the case of thread competition is not intense, use spin lock, use in the case of competition, block lock.

(full text)


Related articles: