可重入锁

可重入锁又名递归锁

是指同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提:锁对象得是同一个对象),不会因为之前已经获取过还没释放而阻塞。

Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁。

 

synchronized底层原理

每个锁对象拥有一个锁计数器和一个指向持有该锁的线程的指针

当执行monitorenter时,如果目标对象的计数器为零,那么说明它没有被其他线程所持有,Java虚拟机会将该锁对象的持有线程设置为当前线程,并且将其计数器加1。

在目标锁对象的计数器不为0的情况下,如果锁对象的持有线程是当前线程,那么Java虚拟机可以将其计数器加1,否则需要等待,直至持有线程释放该锁。

当执行monitorexit时,Java虚拟机则需将锁对象的计数器减1,计数器为零代表锁已被释放。

 

synchronized验证可重入锁

public class ReentrantLockDemo {
    public ReentrantLockDemo() {
    }

    public synchronized void f1() {
        System.out.println("f1");
        f2();
    }

    public synchronized void f2() {
        System.out.println("f2");
        f3();
    }

    public synchronized void f3() {
        System.out.println("f3");
    }

    public static void main(String[] args) {
        ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
        reentrantLockDemo.f1();
    }
}

ReentrantLock验证可重入锁

public class ReentrantLockDemo {
    Lock lock = new ReentrantLock();

    public void m() {
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("1");
                lock.lock();
                try {
                    System.out.println(2);
                } finally {
                    lock.unlock();
                }
            } finally {
                lock.unlock();
            }
        }).start();
    }

    public static void main(String[] args) {
        ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
        reentrantLockDemo.m();
    }
}
posted @ 2024-12-22 17:25  达摩克利斯之剑  阅读(36)  评论(0)    收藏  举报