【问题标题】:Reentrantlock works fine in Java but causes IllegalMonitorException in ScalaReentrantlock 在 Java 中工作正常,但在 Scala 中导致 IllegalMonitorException
【发布时间】:2016-04-08 08:45:56
【问题描述】:

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

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

【问题讨论】:

  • 你的 calculate 方法是否在一个类/特征中?因为在 java 版本中 Lock 是静态的,所以在 scala 中翻译它意味着将它放在一个对象中,不是在定义 calculate 的类/特征中。
  • 另外,这可能是错误的原因,您将LOCK 定义为def,但它实际上应该是val。否则,您每次引用 LOCK 时都会重新创建一个新锁,从而有效地使锁无用。
  • 通常的做法是在尝试之前获取锁,而不是在里面。
  • calculate 方法在一个抽象类中。可能是因为另一个线程试图解锁这个 LOCK ?

标签: java multithreading scala concurrency reentrantlock


【解决方案1】:

您绝对应该将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 调用放在 try 之前。 (与 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()
        }
      }
  }
}

【讨论】:

  • LOCK 无法在“MyClass”中解析。似乎我没有错过什么
猜你喜欢
  • 2021-06-28
  • 1970-01-01
  • 2020-01-13
  • 1970-01-01
  • 2011-04-09
  • 2018-05-19
  • 1970-01-01
  • 2013-06-29
  • 2021-05-09
相关资源
最近更新 更多