可重入锁 = 递归锁。java
(官方概念)指的是同一线程外层函数得到锁以后,内层递归函数仍然能获取到该锁的代码,在同一线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。ide
指的是线程能够进入任何一个它已经拥有的锁所同步的代码块函数
public synchronized void method1() { method2(); } public synchronized void method2() { } /* method1和method2都是同步方法。咱们使 同步方法里面再次访问下一个同步方法。 */
比喻:只要家最外面的大门的锁被打开了,那房间的锁也能通行无阻测试
ReentrantLock
和 Synchronized
就是一个典型的可重入锁spa
可重入锁的最大做用就是避免死锁线程
编写Phone类,在同步方法中,调用另一个同步方法。code
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方法"); } }
测试blog
public static void main(String[] args) { Phone phone = new Phone(); // A线程操做资源列 new Thread(() -> { phone.sendSMS(); }, "线程A").start(); // B线程操做资源列 new Thread(() -> { phone.sendSMS(); }, "线程B").start(); }
运行结果递归
sendSMS()
方法的时候,拥有了一把锁,同时 B 线程没法进入,直到 A 线程拿着锁,执行了sendEmail()
方法后,才释放锁,这样 B 才可以进入。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方法在进入的时候,就加了锁。运行结果
最后输出结果咱们能发现,结果和加synchronized方法是一致的,都是在外层的方法获取锁以后,线程可以直接进入里层。
最后获得的结果也是同样的,由于里面无论有几把锁,其它他们都是同一把锁,也就是说用同一个钥匙都可以打开
获得结果
线程A得到锁 线程A设置锁
也就是说程序直接卡死,线程不能出来,也就说明咱们申请几把锁,最后就要解除几把锁。
运行程序会直接报错!!