概念
可重入锁 = 递归锁。
(官网概念)指的是同一线程外层函数取得锁之后,内层递归函数依然能获取到该锁的代码,在同一线程在外层办法获取锁的时候,在进入内层办法会主动获取锁。
指的是线程能够进入任何一个它曾经领有的锁所同步的代码块
代码解释
public synchronized void method1() {
method2();
}
public synchronized void method2() {
}
/*
method1和method2都是同步办法。咱们使 同步办法外面再次拜访下一个同步办法。
*/
- 咱们如果取得了method1的锁,method2也加锁了,那么它们领有的是同一把锁。
- 也就是说,咱们只有拿到method1办法的锁,进入到method1后,能间接进入method2办法。因为他们的锁是同一把。
比喻:只有家最里面的大门的锁被关上了,那房间的锁也能通行无阻
作用
ReentrantLock
和 Synchronized
就是一个典型的可重入锁
可重入锁的最大作用就是防止死锁
可重入锁验证
验证Synchronized
编写Phone类,在同步办法中,调用另外一个同步办法。
public class Phone {
// 发送短信的办法
public synchronized void sendSMS() {
System.out.println(Thread.currentThread().getName() + "调用了sendSMS办法");
sendEmail(); // 再同步办法内,调用另外一个同步办法
}
// 发送邮件的办法
public synchronized void sendEmail() {
System.out.println(Thread.currentThread().getName() + "调用了sendEmail办法");
}
}
测试
public static void main(String[] args) {
Phone phone = new Phone();
// A线程操作资源列
new Thread(() -> {
phone.sendSMS();
}, "线程A").start();
// B线程操作资源列
new Thread(() -> {
phone.sendSMS();
}, "线程B").start();
}
运行后果
- 这就阐明当 A 线程进入
sendSMS()
办法的时候,领有了一把锁,同时 B 线程无奈进入,直到 A 线程拿着锁,执行了sendEmail()
办法后,才开释锁,这样 B 才可能进入。
证实ReentrantLock
public class Phone implements Runnable {
Lock lock = new ReentrantLock();
//getLock办法
public void getLock() {
lock.lock();
System.out.println(Thread.currentThread().getName() + "取得锁");
setLock(); //调用setLock办法
lock.unlock();
}
//setLock办法
public void setLock() {
lock.lock();
System.out.println(Thread.currentThread().getName() + "设置锁");
lock.unlock();
}
//重写run办法
@Override
public void run() {
getLock();
}
}
测试
public static void main(String[] args) {
Phone phone = new Phone();
// 因为Phone实现了Runnable接口
Thread A = new Thread(phone, "线程A");
Thread B = new Thread(phone, "线程B");
A.start();
B.start();
}
- 当初咱们应用
ReentrantLock
进行验证,首先资源类实现了Runnable接口,重写Run办法,外面调用getLock办法,getLock办法在进入的时候,就加了锁。 - 而后在办法外面,又调用另外一个加了锁的setLock办法
运行后果
最初输入后果咱们能发现,后果和加synchronized办法是统一的,都是在外层的办法获取锁之后,线程可能间接进入里层。
- 当咱们再getLock办法加两把锁会是什么状况呢?
最初失去的后果也是一样的,因为外面不论有几把锁,其它他们都是同一把锁,也就是说用同一个钥匙都可能关上
- 当咱们在getLock办法加两把锁,然而只解一把锁会呈现什么状况呢?
失去后果
线程A取得锁
线程A设置锁
也就是说程序间接卡死,线程不能进去,也就阐明咱们申请几把锁,最初就要解除几把锁。
- 当咱们只加一把锁,然而用两把锁来解锁的时候,又会呈现什么状况呢?
运行程序会间接报错!!