[英]Multithreaded correctness: Using synchronized block
我正在使用CMU Sphinx语音识别器库( Link to source ),它使用了一些synchronized
块。
来自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; }
说实话,我不太了解错误描述,在这种情况下应该是错误的。 全局变量不是字段吗? 如果没有,我该如何改进代码呢?
/ edit:这是调用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;
}
此代码实际上也使用了synchronized
语句。 使用它是否有意义?
synchronized块“捕获”给定对象的锁,在您的情况下为mailbox
表示的对象。 将变量mailbox
更改为指向其他对象后,其他线程可以“捕获”此对象的锁定而不会出现问题,因为它不会被捕获。
请注意,锁定用于对象,而不是用于引用!
现在,concider以下[伪代码]:
synchronised (myObject) {
myObject = new Object();
i += 5; //assume i is an instance variable
}
实际上这里没有锁! 每个线程都在锁定块中创建一个新对象,并且i的修改不同步!
我不认为它适用于你的情况。 你有一个notifyAll()
调用,这意味着在其他线程的代码中的某个地方有一个匹配的wait()
调用:
synchronized (this.mailbox) {
this.mailbox.wait();
}
这意味着另一个线程将在等待通知时放弃锁定。
您的代码检查员可能会被该行混淆:
this.mailbox = Event.START;
意味着你可能同时修改这个对象,这样如果另一个线程试图获取this.mailbox
上的锁,它将看到一个不同的对象。 但是,我确实认为,因为:
this.mailbox
全局可见 所有线程应始终具有同步对象的更新视图。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.