可重入锁公平性

ReentrantLock Fairness

我的 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

您的用法已损坏。你调用 tryLock,它可能锁定也可能不锁定(它的布尔值 returns 告诉你发生了什么)。

如果 tryLock 有效,你 立即调用 lock() 第二次 ,这很好,因为它是一个可重入锁,但你也现在需要调用 unlock() 两次你没有做的。 每次调用 lock() 和每次 true 返回调用 tryLock 必须伴随一个 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
}

如果您的锁定调用后没有紧跟着关键字 try,您的代码就被破坏了。请注意,锁 class 的 javadoc 提到了这一点,并在所有相关示例中显示了这一点。 ReentrantLock javadoc - 它就在顶部。