可重入锁(也叫做递归锁)
干货
指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
也即是说,线程可以进入任何一个它已经拥有的锁所同步着的代码块。
ReentrantLock/synchronized就是一个典型的可重入锁。
可重入锁最大的作用是避免死锁
举例
生活小例子,只是为了方便理解记忆,不要太较真
家里有一个大门是有锁的,然后厨房、卧室、卫生间等也是有锁的。
回家的时候打开大门的锁,然后通常情况下也能进入到厨房、卧室、卫生间等房间(不要杠精,你家厨房、卧室、卫生间出门全都锁着的除外)
代码演示
public class SynchronizedReentrantLockDemo {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
//t1、t2两个线程演示synchronized的可重入
new Thread(()->{
phone.sendMsg();
},"t1").start();
new Thread(()->{
phone.sendMsg();
},"t2").start();
Thread.sleep(2000);
System.out.println("=======================");
//t3、t4两个线程演示synchronized的可重入
phone2 phone2 = new phone2();
new Thread(phone2,"t3").start();
new Thread(phone2,"t4").start();
}
}
class Phone{
public synchronized void sendMsg() {
System.out.println(Thread.currentThread().getName() + "\t come in sendMsg()");
sendEmail();
}
public synchronized void sendEmail() {
System.out.println(Thread.currentThread().getName() + "\t come in sendEmail()");
}
}
class phone2 implements Runnable {
Lock lock = new ReentrantLock();
public void getLock() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "\t enter getLock()");
setLock();
}finally {
lock.unlock();
}
}
public void setLock() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "\t enter setLock()");
}finally {
lock.unlock();
}
}
@Override
public void run() {
getLock();
}
运行结果
t1 come in sendMsg()
t1 come in sendEmail()
t2 come in sendMsg()
t2 come in sendEmail()
=======================
t3 enter getLock()
t3 enter setLock()
t4 enter getLock()
t4 enter setLock()