Java 为什么书中的ReentrantLock算法不起作用?
今天我读了一篇文章,发现了一件我个人很难理解的事情 因此,我找到了java中的ReentrantLock实现(对我来说,是第188页,第8章): 我分析了这段代码,但仍然没有完全理解它 因此,我可以通过以下方式使用Java 为什么书中的ReentrantLock算法不起作用?,java,multithreading,concurrency,Java,Multithreading,Concurrency,今天我读了一篇文章,发现了一件我个人很难理解的事情 因此,我找到了java中的ReentrantLock实现(对我来说,是第188页,第8章): 我分析了这段代码,但仍然没有完全理解它 因此,我可以通过以下方式使用java.util.concurrent.locks中的ReentrantLock: lock.lock(); lock.lock(); // Some code here... lock.unlock(); lock.unlock(); 这样就可以了,因为它是可重入锁定的,我可以多
java.util.concurrent.locks
中的ReentrantLock
:
lock.lock();
lock.lock();
// Some code here...
lock.unlock();
lock.unlock();
这样就可以了,因为它是可重入锁定的,我可以多次获得临界截面
例如,您可以从本书中找到自旋锁实现:
class TASLock implements Lock {
private AtomicBoolean state = new AtomicBoolean(false);
@Override
public void lock() {
while(state.getAndSet(true));
}
@Override
public void unlock() {
state.set(false);
}
// Other Lock methods...
}
此实现按预期工作
因此,您可以从simpleentrantlock
中注意到下一件事:
lock = new SimpleLock();
正如作者告诉我们的:
我们将内部锁字段初始化为(虚构的)SimpleLock类的对象,该类可能不可重入
但实际上,我已经实现了非重入锁(TASLock
),所以我将进行下一个内联:
lock = new TTASLock();
最后,当我尝试执行下一个代码时,我将出现死锁:
new Thread(() -> {
lock.lock();
lock.lock();
System.out.println("No deadlock found.");
lock.unlock();
lock.unlock();
}).start();
这看起来很清楚,因为在lock
方法中,我们有这样的代码:
lock.lock();
实际上,我们在没有任何先决条件的情况下,尝试在同一个锁对象上获取两次临界截面
书中是否指出了错误的算法?或者我不明白什么吗?lock()方法中缺少lock.unlock()。算法是正确的,这是一个简单的疏忽。如书中所述: 因为这两个字段是原子操作的,所以我们需要一个内部短期锁 为了回答评论中的问题,下面是lock()的更正版本:
现在你的问题是什么?@RavindraRanwala我的问题是:书中指出的算法是错误的吗?或者我不明白什么吗?因为在这本书中,互斥的这种算法被称为“可重入的”,正如我所看到的,实际上不是。所以,我有点困惑,这就是为什么我要问这个问题。为什么你说它不可重入或不工作?你有什么证据?@Ravindranwala reentrant lock没有死锁,如果你在同一个互斥锁上多次获得它。所以,请检查我的例子。无论如何,你可以自己测试它,因为我共享了代码(从书中)。你能告诉我这个解锁在代码中遗漏了什么吗?我把它添加到了anwserSo中,它看起来像书中的一个打字错误。
lock.lock();
public void lock() {
long me = Thread.currentThread().getId();
lock.lock();
try{
if (owner == me) {
holdCount++;
return;
}
while (holdCount != 0) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
owner = me;
holdCount = 1L;
} finally {
lock.unlock(); // this call is missing
}
}