Вы обязательно должны сделать 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()
}
}
}
Это прямой перевод на scala вашего исходного кода Java.
Наконец, в своем (теперь удаленном) ответе Джон Скит справедливо предлагает:
Вы должны разблокировать блокировку только в том случае, если вам удалось ее получить, и обычный шаблон заключается в том, чтобы поместить вызов 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()
}
}
}
}
person
Régis Jean-Gilles
schedule
08.04.2016
calculate
случайно не относится к классу/признаку? Поскольку в версии JavaLock
является статическим, поэтому перевод этого в scala означал бы помещение его в объект, не в класс/признак, где определеноcalculate
. - person Régis Jean-Gilles   schedule 08.04.2016LOCK
какdef
, но на самом деле это должно бытьval
. В противном случае вы воссоздаете новую блокировку каждый раз, когда ссылаетесь наLOCK
, эффективно делая блокировку бесполезной. - person Régis Jean-Gilles   schedule 08.04.2016