可重入锁的含义及解决的问题

可重入锁顾名思义可以重复利用的锁,但不是任何方法都能重复使用,而是最初占有锁的方法调用的方法,即是调用方法与被调方法可以同时占用同一把锁。
下面从三个角度来说明:
1.被调方法没有加锁

public class LockTest {
    private static final Object obj=new Object();
    public void method1(){
        synchronized (obj){
            System.out.println("method1执行了");
            method2();
            System.out.println("回到了method1");
        }
    }
    public void method2(){
        System.out.println("method2执行了");
    }

    public static void main(String[] args) {
        LockTest lockTest=new LockTest();
        lockTest.method1();
    }
}

这种情况只有method1占用了锁,在调用method2,method1等待method2执行完即可再次执行释放锁
执行结果:

method1执行了
method2执行了
回到了method1

2.被调方法需要同样的锁,该锁为可重入锁

public class LockTest {
    private static final Object obj=new Object();
    public void method1(){
        synchronized (obj){
            System.out.println("method1执行了");
            method2();
            System.out.println("回到了method1");
        }
    }
    public void method2(){
        synchronized (obj) {
            System.out.println("method2执行了");
        }
    }

    public static void main(String[] args) {
        LockTest lockTest=new LockTest();
        lockTest.method1();
    }
}

这种情况method1先占用了锁,之后调用method2,发现method2也需要相同的锁,因为method2是method1的调用方法和synchronized是可重入锁(Reentrantlock也是)这两个条件,method2也占用了这把锁,即是method1,method2占用了同一把锁。
执行结果:

method1执行了
method2执行了
回到了method1

3.被调方法需要同样的锁,该锁是不可重入锁
因为jdk自带的锁都是可重入锁,采用在method2的synchronized锁前添加wait的方式模拟不可重入锁

public class LockTest {
    private static final Object obj=new Object();
    public void method1() throws InterruptedException {
        synchronized (obj){
            System.out.println("method1执行了");
            method2();
            System.out.println("回到了method1");
        }
    }
    public void method2() throws InterruptedException {
        wait();
        synchronized (obj) {
            System.out.println("method2执行了");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        LockTest lockTest=new LockTest();
        lockTest.method1();
    }
}

这种情况也是method1先占用了锁,之后调用method2,发现method2也需要相同的锁,但不同的是:此时的锁是不可重入锁(模拟的)。method2因为拿不到锁不能继续执行,需要method1释放锁,而method1也在等待method2执行完后进行下一步操作,这样就相互等待产生死锁。
执行结果:

method1执行了
Exception in thread "main" java.lang.IllegalMonitorStateException
	at java.base/java.lang.Object.wait(Native Method)
	at java.base/java.lang.Object.wait(Object.java:328)
	at com.heimaweb.day1.LockTest.method2(LockTest.java:18)
	at com.heimaweb.day1.LockTest.method1(LockTest.java:13)
	at com.heimaweb.day1.LockTest.main(LockTest.java:26)

method2并没有输出

总结:可重入锁是调用方法与被调方法可以同时调用的一种锁,它的作用是防止调用方法与被调方法方法相互等待产生死锁现象。(因为jdk中自带的锁基本上都是可重入锁,所以可以放心用)

posted @ 2024-01-27 15:11  liu52program小白  阅读(172)  评论(0)    收藏  举报