Reentrantlock 在 Java 中工作正常,但在 Scala 中导致 IllegalMonitorException
Reentrantlock works fine in Java but causes IllegalMonitorException in Scala
我想迁移 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。我不明白为什么会发生这种情况。
谁能告诉我问题出在哪里?
你绝对应该让 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 在他(现已删除)的回答中正确地建议:
You should only unlock the lock if you managed to acquire it - and the
conventional pattern is to put the lock/tryLock call before the try.
(It doesn't matter with tryLock(), but it does matter for lock(), so
we might as well be consistent.)
给出:
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()
}
}
}
}
我想迁移 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。我不明白为什么会发生这种情况。
谁能告诉我问题出在哪里?
你绝对应该让 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 在他(现已删除)的回答中正确地建议:
You should only unlock the lock if you managed to acquire it - and the conventional pattern is to put the lock/tryLock call before the try. (It doesn't matter with tryLock(), but it does matter for lock(), so we might as well be consistent.)
给出:
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()
}
}
}
}