如何使用 ReentrantLock 锁定?

How to lock with ReentrantLock?

我希望下面的测试只打印一次 "has been locked"。 但是它因此打印了该行。

public class LocKTest {
    @Test
    public void testLock() {
        Lock lock = new ReentrantLock();
        while (true) {
            if (lock.tryLock()) {
                //lock.lock(); same result if I include an explicit lock here
                System.out.println("has been locked");
            }
        }
    }
}

据我了解,tryLock 将尽可能锁定 ReentrantLock(即如果尚未锁定)。但显然不是这样。

如何设置这样的线程安全锁?

名称是 ReentrantLock,这意味着如果您已经拥有锁,则可以 re-enter

如果您希望拥有线程块,您可以使用具有 1 个(或更多)许可的 Semaphore

引用tryLock()的文档(粗体字是我加的):

Acquires the lock if it is not held by another thread and returns immediately with the value true, setting the lock hold count to one

在这种情况下,当前线程持有锁,因此您可以多次重新进入("re-acquire")。如果您 运行 从不同的线程循环的每次迭代,第一个将获得锁,而第二个将无法获得它。

考虑到 ,您可以实施自己的 Lock class:

public class Lock {

    private boolean isLocked = false;

    public synchronized void lock() throws InterruptedException {
        while(isLocked) {
            wait();
        }
        isLocked = true;
    }

    public synchronized void unlock() {
        isLocked = false;
        notify();
    }
}

这样使用:

public class LocKTest {
    @Test
    public void testLock() {
        Lock lock = new Lock();
        while (true) {
            if (lock.lock()) {
                System.out.println("has been locked"); // prints only once
            }
        }
    }
}

取自 this tutorial 的代码示例。