关于java:9Java锁之可重入锁

3次阅读

共计 1938 个字符,预计需要花费 5 分钟才能阅读完成。

概念

可重入锁 = 递归锁。

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

指的是线程能够进入任何一个它曾经领有的锁所同步的代码块

代码解释

public synchronized void method1() {method2();        
}
    
public synchronized void method2() {}
/*
    method1 和 method2 都是同步办法。咱们使 同步办法外面再次拜访下一个同步办法。*/
  • 咱们如果取得了 method1 的锁,method2 也加锁了,那么它们领有的是 同一把锁
  • 也就是说,咱们只有拿到 method1 办法的锁,进入到 method1 后,能间接进入 method2 办法。因为他们的锁是同一把。

比喻:只有家最里面的大门的锁被关上了,那房间的锁也能通行无阻

作用

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

可重入锁的最大作用就是 防止死锁

可重入锁验证

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

运行后果

最初输入后果咱们能发现,后果和 加 synchronized 办法是统一的,都是在外层的办法获取锁之后,线程可能间接进入里层。

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

最初失去的后果也是一样的,因为外面不论有几把锁,其它他们都是同一把锁,也就是说用同一个钥匙都可能关上

  • 当咱们在 getLock 办法加两把锁,然而只解一把锁会呈现什么状况呢?

失去后果

线程 A 取得锁
线程 A 设置锁

也就是说 程序间接卡死,线程不能进去,也就阐明咱们申请几把锁,最初就要解除几把锁。

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

运行程序会间接报错!!

正文完
 0