As a tool for concurrently sharing data and ensuring consistency, locks have multiple implementations on the JAVA platform (such as synchronized and ReentrantLock, etc.). These already written locks provide convenience for our development, but the specific nature and type of the locks are rarely mentioned. This series of articles will analyze common lock names and characteristics under JAVA to answer your questions.
4. Reentrant lock:
This article talks about reentrant locks in a broad sense, not just ReentrantLock under JAVA.
Reentrant locks, also called recursive locks, mean that after the outer function of the same thread acquires the lock, the inner recursive function still has the code to acquire the lock, but it is not affected.
In the JAVA environment, ReentrantLock and synchronized are both reentrant locks.
Here are usage examples:
Copy the code code as follows:
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 final results of both examples are correct, that is, the same thread ID is output twice consecutively.
The result is as follows:
Copy the code code as follows:
Threadid: 8
Threadid: 8
Threadid: 10
Threadid: 10
Threadid: 9
Threadid: 9
The biggest role of reentrant locks is to avoid deadlocks.
Let's take spin lock as an example.
Copy the code code as follows:
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 the same thread calls lock() twice, it will cause the lock position to be called for the second time to spin. If a deadlock occurs, it means that the lock is not reentrant. (In the lock function, you should verify whether the thread is the thread that has obtained the lock)
2. If problem 1 has been solved, the lock will have been released when unlock() is called for the first time. The lock should not actually be released.
(Using counting times for statistics)
After modification, it is as follows:
Copy the code code 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);
}
}
}
}
This spin lock is a reentrant lock.