NotifyAll ()가 정수에 동기화 될 때 불법 모니터 스테이트 렉션을 올리는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/260337

문제

이 테스트 프로그램이 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");
}

산출:

성공

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top