可重入与不可重入锁

146 阅读2分钟

可重入(Reentrant)和不可重入(Non-reentrant)锁是两种锁的概念,它们主要涉及到在同一线程中是否可以多次获取同一把锁。

  1. 可重入锁(Reentrant Lock)

    • 可重入锁允许同一个线程在持有锁的同时再次获取该锁,而不会发生死锁。这种特性使得线程可以递归地调用同步方法或代码块,而不用担心自己已经持有锁。
    class ReentrantExample {
        private final ReentrantLock lock = new ReentrantLock();
    
        public void outer() {
            lock.lock();
            try {
                inner();
            } finally {
                lock.unlock();
            }
        }
    
        public void inner() {
            lock.lock();
            try {
                // 一些处理
            } finally {
                lock.unlock();
            }
        }
    }
    

    在上面的例子中,outer 方法和 inner 方法都可以获取 lock,因为它是可重入的。

  2. 不可重入锁(Non-reentrant Lock)

    • 不可重入锁指的是在同一个线程中,如果已经持有了某个锁,再次去获取这个锁会导致死锁或者产生其他错误。不可重入锁通常不允许同一个线程在没有释放锁的情况下再次获取同一把锁。
    class NonReentrantExample {
        private final NonReentrantLock lock = new NonReentrantLock();
    
        public void outer() {
            lock.lock();
            try {
                inner();  // 试图再次获取锁,可能导致死锁或其他问题
            } finally {
                lock.unlock();
            }
        }
    
        public void inner() {
            lock.lock();  // 试图获取同一把锁,可能导致问题
            try {
                // 一些处理
            } finally {
                lock.unlock();
            }
        }
    }
    

    上面的例子中,inner 方法试图再次获取 lock,这可能导致死锁或其他问题。

在实际应用中,可重入锁更为常见,因为它更灵活,允许同一线程递归地获取同一把锁,简化了编程模型。Java中的 ReentrantLock 就是一个可重入锁的例子。非重入锁在使用上需要更谨慎,因为它不允许同一线程多次获取同一把锁,容易引发错误。不过,在某些特殊情况下,非重入锁可能会被用于实现一些特定的同步机制。