同步锁定是Reentrantlock还是仅锁定其对象?

fbe*_*oit 4 java java.util.concurrent

具有ReentrantLock和lock()/ unlock()的普通模式如下所示:

lck.lock();
try {
    // ...
}
finally {
    lck.unlock();
}
Run Code Online (Sandbox Code Playgroud)

可以重构为

synchronized(lck) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)


又为什么呢

Ser*_*nov 6

这些是不同的东西。synchronized内置于语言中,可与任何对象一起使用。它所做的就是锁定其固有的锁定。每个对象都有一个。由于它是一种内置机制,因此您不需要try-finally块-当控件退出该synchronized块时,锁总是解锁的。因此,只要您的代码实际退出该块,锁就会被解锁。

ReentrantLock是一个特殊的班级。它锁定了一些特殊的内部对象,该对象可能是特定于实现的。它并没有锁住其内在的锁。当然,您也可以锁定那个锁,但是通常没有任何意义。这段代码几乎肯定会死锁,例如:

final ReentrantLock lock = new ReentrantLock();
new Thread(() -> {
    lock.lock();
    try {
        System.out.println("Thread 1 locked the lock");
        try { Thread.sleep(100); } catch (Exception ex) {}
        synchronized (lock) {
            System.out.println("Thread 1 locked lock's intrinsic lock");
        }
    } finally {
        lock.unlock();
    }
}).start();
new Thread(() -> {
    synchronized (lock) {
        System.out.println("Thread 2 locked lock's intrinsic lock");
        try { Thread.sleep(200); } catch (Exception ex) {}
        lock.lock();
        try {
            System.out.println("Thread 2 locked the lock");
        } finally {
            lock.unlock();
        }
    }
}).start();
Run Code Online (Sandbox Code Playgroud)

它死锁是因为两个线程以不同的顺序锁定了两个不同的事物。

当然感觉就像在ReentrantLock做一样的事情synchronized。它的工作原理类似,但synchronized更方便,功能也更差。因此,除非您需要的任何功能(ReentrantLock例如可中断的锁定尝试或锁定超时),否则应坚持使用synchronized以重入锁定为目的,并为此使用任何对象。简单private final Object lock = new Object()就可以了。请注意,这final将防止在您暂时更改该对象时可能造成的混淆。如果您省略某些IDE,则会发出警告final