Я использую библиотеку CMU Sphinx Speech Recognizer ( Ссылка на источник ), в которой используются блоки 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
.Имеет ли смысл вообще его использовать?