【问题标题】:ReentrantLock Fairness可重入锁公平
【发布时间】:2026-01-15 21:15:01
【问题描述】:

我的 ReentrantLock 没有按我的预期工作。我希望下面代码的结果是随机锁定和解锁两个线程,但我得到的结果总是在一个线程上解锁。任何人都可以解释 ReentrantLock,我正在尝试了解它的公平政策(即新的 ReentrantLock(true))以及 tryLock() 方法。谢谢。

    final ReentrantLock lock = new ReentrantLock(true);
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true)
                try{
                    if (lock.tryLock(1, TimeUnit.SECONDS)) {
                        lock.lock();
                        System.out.println(Thread.currentThread().getName() + " locked");
                        lock.unlock();
                    } else {
                        System.out.println(Thread.currentThread().getName() + " not locked");
                    }
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
    }).start();
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true)
                try{
                    if (lock.tryLock(1, TimeUnit.SECONDS)) {
                        lock.lock();
                        System.out.println(Thread.currentThread().getName() + " locked");
                        lock.unlock();
                    } else {
                        System.out.println(Thread.currentThread().getName() + " not locked");
                    }
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
    }).start();

控制台中的结果:

Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked
Thread-1 not locked
Thread-0 locked

【问题讨论】:

    标签: java reentrantlock


    【解决方案1】:

    您的用法已损坏。你打电话给tryLock,它可能会锁定也可能不会锁定(它返回的布尔值会告诉你发生了什么)。

    如果tryLock 有效,你立即第二次调用lock(),这很好,因为它是一个可重入锁,但你现在还需要调用unlock() 两次,这你没有做。 lock() 的每个调用和对tryLock 的每个true-returning 调用都必须伴随一个unlock() 调用。

    因此,无论哪个线程赢得比赛,都永远不会释放锁,因为您没有匹配您的锁调用。

    鉴于您必须解锁,实际上只有一种方法可以使用锁定:

    someLock.lock();
    try {
      do stuff here
    } finally {
      someLock.unlock();
    }
    

    tryLock:

    if (someLock.tryLock()) try {
      code goes here
    } finally {
      someLock.unlock();
    } else {
      code here if lock was not available
    }
    

    如果您的 lock 调用没有紧跟关键字 try,则您的代码已损坏。请注意,锁类的 javadoc 提到了这一点,并在所有相关示例中显示了这一点。 ReentrantLock javadoc - 就在顶部。

    【讨论】:

    • 好的,使用正确的锁现在一切顺利。