我正在使用一些使用塊的CMU Sphinx語音識別器庫(Link to source)。從RecognizerTask多線程的正確性:使用同步塊
一個例子塊:
Event mailbox;
[...]
public void start() {
synchronized (this.mailbox) {
this.mailbox.notifyAll();
this.mailbox = Event.START;
}
}
代碼工作沒有任何問題,但是BugFinder給出了這樣的警告:
錯誤:同步上RecognizerTask.mailbox在妄圖 後衛它
此方法在似乎是 嘗試防止同時發生的字段上同步更新該字段。但是 守護字段會鎖定引用的對象,而不是在 字段上。這可能不會提供您需要的互斥,而其他線程可能正在獲取對引用對象的鎖定(對於其他 目的)。這種模式的一個例子是:
private Long myNtfSeqNbrCounter = new Long(0); private Long getNotificationSequenceNumber() { Long result = null; synchronized(myNtfSeqNbrCounter) { result = new Long(myNtfSeqNbrCounter.longValue() + 1); myNtfSeqNbrCounter = new Long(result.longValue()); } return result; }
說實話,我不太明白的錯誤描述,什麼應該是錯在這種情況下。 是一個全局變量而不是一個字段?如果不是,我該如何改進代碼?
/編輯:這是Event.wait()
被稱爲僅部分:
Event todo = Event.NONE;
synchronized (this.mailbox) {
todo = this.mailbox;
/* If we're idle then wait for something to happen. */
if (state == State.IDLE && todo == Event.NONE) {
try {
//Log.d(getClass().getName(), "waiting");
this.mailbox.wait();
todo = this.mailbox;
//Log.d(getClass().getName(), "got" + todo);
} catch (InterruptedException e) {
/* Quit main loop. */
//Log.e(getClass().getName(), "Interrupted waiting for mailbox, shutting down");
todo = Event.SHUTDOWN;
}
}
/* Reset the mailbox before releasing, to avoid race condition. */
this.mailbox = Event.NONE;
}
此代碼實際上是使用聲明爲好。使用它有意義嗎?
你是對的。警告是正確的,同步不會做大多數人會認爲它做的事。但在這種情況下,這並不重要。線程只是在一個無關緊要的地方持有'錯誤的'鎖 - '不正確'鎖定的代碼不需要鎖定,因爲它會自動分配一個引用。 – 2012-01-09 11:13:50
非常感謝您的回答!請看我更新的問題 - 你會建議完全刪除'synchronized'嗎? – Force 2012-01-09 16:44:46
實際上,你不能這樣做,因爲對象上的等待或通知/ notifyAll調用必須位於同一個對象上的同步塊內。 – Tudor 2012-01-09 20:08:23