0

我想迁移一个 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 。我看不出发生这种情况的任何原因。

谁能告诉我问题出在哪里?

4

1 回答 1

4

您绝对应该制作LOCKaval而不是 a defReetrantLock就目前而言,您每次都在重新创建一个新实例。实际上,您正在做的是:

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代码的直接翻译。

最后,在他(现已删除)的回答中,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()
        }
      }
  }
}
于 2016-04-08T09:01:47.740 回答