Introduction to reentrant locks for Java locks

  • 2020-04-01 03:34:29
  • 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.

Iv. Reentrant lock:

This article is about reentrant locking in a broad sense, not ReentrantLock in JAVA alone.

A reentrant lock, also known as a recursive lock, is when an outer function of the same thread acquires a lock and the inner recursive function still has the code to acquire the lock, but it is not affected.
In the JAVA environment, both ReentrantLock and synchronized are reentrant locks.

Here is the usage example:


public class Test implements Runnable{  public synchronized void get(){
  System.out.println(Thread.currentThread().getId());
  set();
 }  public synchronized void set(){
  System.out.println(Thread.currentThread().getId());
 }  @Override
 public void run() {
  get();
 }
 public static void main(String[] args) {
  Test ss=new Test();
  new Thread(ss).start();
  new Thread(ss).start();
  new Thread(ss).start();
 }
}

The end result of both examples is correct, that is, the same thread id is printed twice in a row.

The results are as follows:


Threadid: 8
Threadid: 8
Threadid: 10
Threadid: 10
Threadid: 9
Threadid: 9

The biggest benefit of reentrant locking is to avoid deadlocks.
Let's take a spin lock as an example.


public class SpinLock {
 private AtomicReference<Thread> owner =new AtomicReference<>();
 public void lock(){
  Thread current = Thread.currentThread();
  while(!owner.compareAndSet(null, current)){
  }
 }
 public void unlock (){
  Thread current = Thread.currentThread();
  owner.compareAndSet(current, null);
 }
}

For spin locks:

1. If there are two calls to lock() from the same thread, it will cause the second call to lock position to spin, resulting in deadlock
Indicates that the lock is not reentrant. (within the lock function, verify that the thread is the one that has the lock)
2. If the 1 problem is resolved, the lock is released the first time the unlock () is called. The lock should not actually be released.
(count times for statistics)

After modification, it is as follows:


public class SpinLock1 {
 private AtomicReference<Thread> owner =new AtomicReference<>();
 private int count =0;
 public void lock(){
  Thread current = Thread.currentThread();
  if(current==owner.get()) {
   count++;
   return ;
  }   while(!owner.compareAndSet(null, current)){   }
 }
 public void unlock (){
  Thread current = Thread.currentThread();
  if(current==owner.get()){
   if(count!=0){
    count--;
   }else{
    owner.compareAndSet(current, null);
   }   }  }
}

The spin lock is reentrant.


Related articles: