Sonar报告以下问题:
Multithreaded correctness - Method does not release lock on all
exception paths findbugs : UL_UNRELEASED_LOCK_EXCEPTION_PATH
This method acquires a JSR-166 (java.util.concurrent) lock, but does not release it on all exception paths out of the method. In general, the correct idiom for using a JSR-166 lock is:
Lock l = ...;
l.lock();
try {
// do something
} finally {
l.unlock();
}
在此代码段中:
public synchronized void put(T element) throws PreconditionException {
Precondition.notNull(element, "Nullobject is not allowed");
lock.lock();
try {
buffer[writeIndex++] = element;
if (writeIndex >= capacity) {
writeIndex = 0;
}
if (size.get() >= capacity) {
// buffer is full
readIndex++;
lastOverflow.set(System.currentTimeMillis());
if (readIndex >= capacity) {
readIndex = 0;
}
return;
}
size.incrementAndGet();
} finally {
try {
notEmpty.signal();
} catch (Exception e) {
e.printStackTrace();
}
lock.unlock();
}
}
我不明白,出于什么原因,这不安全?
答案 0 :(得分:4)
我认为它表明,如果你的代码在行notEmpty.signal();
上抛出另一个Throwable的子类(例如Error),那么锁将不会被释放。
您可以争辩说,如果出现错误,您的应用程序将关闭,或者在此代码中捕获Exception
是正确的做法。我同意这一点,但正如FindBugs所说,有一些代码路径最终导致锁定没有被释放......并且没有什么能阻止开发人员扩展Throwable:'(。
答案 1 :(得分:4)
你可以为解锁添加一个finally,以确保它被调用,与可能导致try-catch的异常路径形成鲜明对比。
此外,捕获异常并仅记录它,不应该保留用于生产,因为您肯定知道。
} finally {
try {
notEmpty.signal();
} catch (Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}