synchronized
블록을 사용하는 CMU Sphinx Speech Recognizer 라이브러리 (Link to source)를 사용하고 있습니다. RecognizerTask에서다중 스레드 정확성 : 동기화 된 블록 사용
한 예 블록 : 가드 RecognizerTask.mailbox에 동기화 헛된 시도 :
버그 :
코드는 아무 문제없이 작동Event mailbox; [...] public void start() { synchronized (this.mailbox) { this.mailbox.notifyAll(); this.mailbox = Event.START; } }
그러나 BugFinder이 경고를 제공합니다 그것
이 방법은 동시 발생을 막기위한 것으로 보이는 필드에서 동기화됩니다 해당 필드에 대한 업데이트. 그러나 필드를 지키고있는 은 필드가 아니라 참조 된 개체에 대한 잠금을 가져옵니다. 다른 사용자가 필요로하는 상호 배타를 제공하지 않을 수 있으며 다른 스레드가 참조 된 객체에 대한 잠금을 획득 할 수 있습니다 (다른 목적). 이 패턴의 예는 다음과 같습니다
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 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
문을 사용한다 : 이것은 Event.wait()
가 호출되는 유일한 부분입니다. 그것을 사용하는 것이 전혀 의미가 있습니까?
정확합니다. 동기화가 대부분의 사람들이 생각하는대로하지 않는다는 경고가 정확합니다. 그러나이 경우 중요하지 않습니다. 쓰레드는 중요하지 않은 곳에 '잘못된'자물쇠만을 붙잡고있다. '부적절한'잠긴 코드는 원자 적으로 참조를 할당하기 때문에 자물쇠가 필요 없다. –
답변 해 주셔서 감사합니다. 내 업데이트 된 질문을 참조하십시오 -'synchronized '를 완전히 제거 하시겠습니까? – Force
개체에 대한 알림 또는 알림/통지는 동일한 개체의 동기화 된 블록 안에 있어야하기 때문에 실제로는 할 수 없습니다. – Tudor