我想迁移一个Java函数
protected static final Lock LOCK = new ReentrantLock();
public double calculate(...){
try {
LOCK.tryLock(20, TimeUnit.SECONDS);
...
}finally{
LOCK.unlock()
}
}
Scala中的相同功能:
protected final def LOCK = new ReentrantLock
def calculate(...): double = {
try{
LOCK.tryLock(20, TimeUnit.Seconds)
...
}finally{
LOCK.unlock()
}
}
LOCK.unlock()
始终导致IllegalMonitorStateException。我没有看到为什么这是开心的原因。
有人可以告诉我问题在哪里吗?
答案 0 :(得分:3)
您绝对应该LOCK
成为val
而不是def
。
就目前而言,您每次都在重新创建ReetrantLock
的新实例。你正在做的就是:
try {
// Useless as we are creating a new lock
(new ReentrantLock).tryLock(20, TimeUnit.SECONDS).tryLock(20, TimeUnit.SECONDS).tryLock(20, TimeUnit.SECONDS);
...
}finally{
// Useless too, and will actually throw because we unlock a fresh (thus unlocked) lock
(new ReentrantLock).unlock()
}
显然必然会失败。
您应该执行以下操作:
object MyClass {
private val LOCK = new ReentrantLock
}
class MyClass {
def calculate(...): double = {
try{
LOCK.tryLock(20, TimeUnit.Seconds)
...
}finally{
LOCK.unlock()
}
}
}
这是对原始java代码的scala的直接翻译。
最后,在他(现已删除)的回答中,Jon Skeet正确地建议:
如果你设法获得锁,你应该只解锁 - 而且 传统模式是在尝试之前调用lock / tryLock。 (与tryLock()无关,但它对lock()很重要,所以 我们也可以保持一致。)
给出了:
object MyClass {
private val LOCK = new ReentrantLock
}
class MyClass {
def calculate(...): double = {
val gotLock = LOCK.tryLock(20, TimeUnit.Seconds)
try {
...
} finally {
if (gotLock) {
LOCK.unlock()
}
}
}
}