我在調查的一些開源代碼中遇到以下情況。它使用一個synchronized塊,其執行以下操作:Java同步塊內的意外狀態
- 設置一個私有布爾實例變量hasListener真
- 來電,做一些wait()的周圍有一個大try塊存儲任何異常荷蘭國際集團的方法一個實例變量內部
- 套hasListener爲false
- 拋出先前存儲
有在同一類中的另一類似方法,該方法不正是在S的任何異常阿米的東西。
從理論上講,這應該確保hasListener在您輸入時只有虛假。然而,以某種方式,底部引發了一個異常(請參閱標記爲//的註釋),因爲它進入方法並且hasListener爲true。我已經檢查過沒有其他地方設置了hasListener,並且默認值爲false。在waitFirstMessage()的底部引發異常會阻止變量被設置爲false嗎?任何其他可能的情況?
從日誌中看,似乎發生了一個合法的異常(「超出完成操作的時間」),並且從此異常(//?)被拋出的頻率相當高。
protected void waitFirstMessage (int msgId) throws LDAPException {
synchronized (this) {
if (!hasListener) {
hasListener = true;
while ((request != null) && (request.id == msgId) &&
(m_exception == null) && (response == null)) {
waitForMessage();
}
hasListener = false;
// Network exception occurred ?
if (m_exception != null) {
LDAPException ex = m_exception;
m_exception = null;
throw ex;
}
} else {
//?
throw new LDAPException();
}
}
}
private void waitForMessage() throws LDAPException {
try {
if (request.timeToComplete > 0) {
long timeToWait = request.timeToComplete -
System.currentTimeMillis();
if (timeToWait > 0) {
wait(timeToWait);
if (notified) {
notified = false;
} else if (request.timeToComplete < System.currentTimeMillis()) {
// Spurious wakeup before timeout.
return;
} else {
request = null;
m_exception = new LDAPException(
"Time to complete operation exceeded",
LDAPException.LDAP_TIMEOUT);
}
} else {
request = null;
m_exception = new LDAPException(
"Time to complete operation exceeded",
LDAPException.LDAP_TIMEOUT);
}
} else {
wait();
notified = false;
}
} catch (InterruptedException e) {
m_exception = new LDAPInterruptedException("Interrupted LDAP operation");
} catch (Exception e) {
m_exception = new LDAPException("Unexpected exception while waiting for response",
LDAPException.OTHER, e.getMessage());
}
}
編輯
好吧,事實證明,我的問題是不正確的。當前在生產中運行日誌的版本比我正在查看的代碼稍早,並且有人明確地解決了這個問題。在以前的版本中waitForMessage()
方法是拋出異常。這些打斷了waitFirstMessage(int msgId)
,然後hasListener
從未被設置爲false。宇宙再次合理。
非常感謝回覆。現在我需要將此修復程序投入生產!
只是爲了確定...(1)'hasListener'沒有在'synchronized'塊之外的其他方法中設置嗎?和(2)'hasListener'不是'static'? –
不是它不是'靜態'。它被初始化爲false,唯一設置的地方就是上面的方法,而另一個地方它完全一樣。 –