NotifyAll ()가 정수에 동기화 될 때 불법 모니터 스테이트 렉션을 올리는 이유는 무엇입니까?
-
06-07-2019 - |
문제
이 테스트 프로그램이 a로 발생하는 이유는 무엇입니까? java.lang.IllegalMonitorStateException
?
public class test {
static Integer foo = new Integer(1);
public static void main(String[] args) {
synchronized(foo) {
foo++;
foo.notifyAll();
}
System.err.println("Success");
}
}
결과:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at test.main(test.java:6)
해결책
당신은 그것을 올바르게 언급했습니다 notifyAll
동기화 된 블록에서 호출해야합니다.
그러나 귀하의 경우 자동 박스로 인해 동기화 한 객체는 호출 한 인스턴스가 아닙니다. notifyAll
에. 사실, 새로 증가했습니다 foo
인스턴스는 여전히 스택에 국한되어 있으며 다른 스레드는 wait
전화.
동기화가 수행되는 자체의 변이 가능한 카운터를 구현할 수 있습니다. 응용 프로그램에 따라 Atomicinteger 당신의 필요를 충족시킵니다.
다른 팁
또한 JVM에 의해 인턴 될 수있는 문자열 및 정수와 같은 개체에서 잠금 또는 알림을 받아야합니다 (정수 1 또는 문자열을 나타내는 많은 객체를 생성하지 않도록하기 위해).
정수를 증가 시키면 오래된 Foo가 사라지고 이전 Foo 변수와 동기화되지 않은 새로운 개체 Foo로 교체됩니다.
다음은 Erickson이 위에서 제안한 Atomicinteger의 구현입니다. 이 예에서 foo.notifyall (); java.lang.lang.ilegalmonitorstateexception을 생성하지 않습니다. foo.incrementandget (); 실행됩니다.
import java.util.concurrent.atomic.AtomicInteger;
public class SynchronizeOnAPrimitive {
static AtomicInteger foo = new AtomicInteger(1);
public static void main(String[] args) {
synchronized (foo) {
foo.incrementAndGet();
foo.notifyAll();
}
System.out.println("foo is: " + foo);
}
}
산출:
foo is: 2
Erickson이 지적했듯이, 사후 분쟁 연산자가없는 코드는 오류없이 작동합니다.
static Integer foo = new Integer(1);
public static void main(String[] args) {
synchronized (foo) {
foo.notifyAll();
}
System.out.println("Success");
}
산출:
성공
제휴하지 않습니다 StackOverflow