2016-04-08 2 views
0

Я хотел бы перенести функцию, JavaReentrantLock отлично работает в Java, но вызывает IllegalMonitorException в Scala

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

Ваш 'высчитывает 'метод в классе/признаке? Потому что в java-версии 'Lock' статична, поэтому перевод, что в scala означает, что он помещает его в объект, ** не ** в классе/признаке, где определяется' расчет'. –

+3

Плюс, и это, вероятно, причина ошибки, вы определяете 'LOCK' как 'def', но это действительно должно быть' val'. В противном случае вы создаете новый замок каждый раз, когда вы ссылаетесь на 'LOCK', фактически делая бесполезным блокировку. –

+0

Обычная практика заключается в приобретении замка перед попыткой, а не внутри. –

ответ

3

Вы должны обязательно сделать LOCK a 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.

Наконец, в его (теперь удален) ответ Джон Скит справедливо говорит:

Вы должны только открыть замок, если вам удалось приобрести его - и обычная картина поставить блокировки/tryLock вызова перед попыткой. (Это не имеет значения с tryLock(), но это имеет значение для блокировки(), так мы могли бы также быть последовательными.)

Что дает:

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() 
     } 
     } 
    } 
} 
+0

LOCK не может быть разрешен в «MyClass». Кажется, что я ничего не пропустил – wurmi

+0

AAH. OFC! Теперь он находится в «статическом классе». большое спасибо. !!!! – wurmi

Смежные вопросы