9.Java锁之可重入锁

概念

可重入锁 = 递归锁。java

(官方概念)指的是同一线程外层函数得到锁以后,内层递归函数仍然能获取到该锁的代码,在同一线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。ide

指的是线程能够进入任何一个它已经拥有的锁所同步的代码块函数

代码解释

public synchronized void method1() {
    method2();        
}
    
public synchronized void method2() {    
}
/*
    method1和method2都是同步方法。咱们使 同步方法里面再次访问下一个同步方法。
*/
  • 咱们若是得到了method1的锁,method2也加锁了,那么它们拥有的是同一把锁
  • 也就是说,咱们只要拿到method1方法的锁,进入到method1后,能直接进入method2方法。由于他们的锁是同一把。

比喻:只要家最外面的大门的锁被打开了,那房间的锁也能通行无阻测试

做用

ReentrantLockSynchronized 就是一个典型的可重入锁spa

可重入锁的最大做用就是避免死锁线程

可重入锁验证

验证Synchronized

编写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();
    }

运行结果递归

  • 这就说明当 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();
}
  1. 如今咱们使用ReentrantLock进行验证,首先资源类实现了Runnable接口,重写Run方法,里面调用getLock方法,getLock方法在进入的时候,就加了锁。
  2. 而后在方法里面,又调用另一个加了锁的setLock方法

运行结果

最后输出结果咱们能发现,结果和加synchronized方法是一致的,都是在外层的方法获取锁以后,线程可以直接进入里层。

  • 当咱们再getLock方法加两把锁会是什么状况呢?

最后获得的结果也是同样的,由于里面无论有几把锁,其它他们都是同一把锁,也就是说用同一个钥匙都可以打开

  • 当咱们在getLock方法加两把锁,可是只解一把锁会出现什么状况呢?

获得结果

线程A得到锁
线程A设置锁

也就是说程序直接卡死,线程不能出来,也就说明咱们申请几把锁,最后就要解除几把锁。

  • 当咱们只加一把锁,可是用两把锁来解锁的时候,又会出现什么状况呢?

运行程序会直接报错!!

相关文章
相关标签/搜索