可重入锁(Reentrant Lock),也称作递归锁,是一种特殊的锁机制,它允许同一个线程多次获取同一个锁。
优点是可以避免死锁。
public class WhatReentrant {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (this) {
System.out.println("第1次获取锁,这个锁是:" + this);
int index = 1;
while (true) {
synchronized (this) {
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + this);
}
if (index == 10) {
break;
}
}
}
}
}).start();
}
}
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
public class WhatReentrant2 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
System.out.println("第1次获取锁,这个锁是:" + lock);
int index = 1;
while (true) {
try {
lock.lock();
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + lock);
try {
Thread.sleep(new Random().nextInt(200));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (index == 10) {
break;
}
} finally {
lock.unlock();
}
}
} finally {
lock.unlock();
}
}
}).start();
}
}
可以发现,10次获取的都是同一把锁。
synchronized 块中的锁对象。在 Runnable 的匿名内部类中,this 关键字指的是该匿名内部类的实例,而不是 WhatReentrant 类的实例或任何外部类的实例。
因此,synchronized (this) 实际上是在锁定这个 Runnable 的匿名内部类的实例。这意味着只要这个线程在执行,它就可以无限次地重新进入这个 synchronized 块,因为它总是持有同一个锁(即这个 Runnable 实例的锁)。
可重入锁有
- synchronized
- ReentrantLock
ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock的时候一定要手动释放锁,并且加锁次数和释放次数要一样