我正在使用一些使用块的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