关注「Java视界」公众号,获取更多技术干货

可重入\不可重入锁?

一、不可重入锁

不可重入锁是指当前线程执行中已经获取了锁,如果再次获取该锁时,就会被阻塞。

下面我们以wait/notify来设计一个不可重入锁(此外还可以通过CAS + 自旋来实现):

//wait、notify实现不可重入锁
public class NonReentrantLockDemo1  {
    //记录是否被锁
    private volatile boolean locked = false;

    public synchronized void lock() {
        //当某个线程获取锁成功,其他线程进入等待状态
        while (locked) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //加锁成功,locked 设置为 true
        locked = true;
    }
    //释放锁
    public synchronized void unlock() {
        locked = false;
        notify();
    }
}


//测试类
class ThreadDemo implements Runnable{
    NonReentrantLockDemo lock = new NonReentrantLockDemo();

    public static void main(String[] args) {
        new Thread(new ThreadDemo()).start();
    }
    /**
     * 方法1:调用方法2
     */
    public void method1() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " method1()");
            method2();
        } finally {
            lock.unlock();
        }
    }
    /**
     * 方法2:打印前获取 obj 锁
     * 
     */
    public void method2() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " method2()");
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void run() {
        method1();
    }
}

在这里插入图片描述
结果显示:当线程执行到method1时,已经拿到lock锁,只要该锁没有被释放,其他代码块无法使用此锁来加锁。当该线程再去调用method2时,而method2也需要获取lock才能执行,这样都导致了死锁,这种会出现问题的重入一把锁的情况,叫不可重入锁。

二、可重入锁

可重入锁又叫递归锁,指在同一个线程在外层方法获取锁的时候,进入内层方法会自动获取锁。

这里使用一段代码简单演示ReentrantLock可重入:

private static ReentrantLock lock = new ReentrantLock();

public static void main(String[] args) {
    System.out.println(lock.getHoldCount());
    lock.lock();
    System.out.println(lock.getHoldCount());
    lock.lock();
    System.out.println(lock.getHoldCount());
    lock.unlock();
    System.out.println(lock.getHoldCount());
    lock.unlock();
    System.out.println(lock.getHoldCount());
}
0
1
2
1
0

结果显示:同一个线程获取到ReentrantLock锁后,在不释放该锁的情况下可以再次获取。

可重入性优点:

  • 避免死锁
  • 提升封装性
posted @ 2022-06-25 14:02  沙滩de流沙  阅读(69)  评论(0编辑  收藏  举报

关注「Java视界」公众号,获取更多技术干货