"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > 한 스레드가 통지() 또는 통지All() 후에 항상 객체 잠금을 다시 획득하는 이유는 무엇입니까?

한 스레드가 통지() 또는 통지All() 후에 항상 객체 잠금을 다시 획득하는 이유는 무엇입니까?

2024년 11월 16일에 게시됨
검색:383

Why Does One Thread Always Reacquire the Object Lock After notify() or notifyAll()?

notify()와 informAll()의 미묘한 차이

notify()와 informAll()의 주요 차이점은 다음과 같습니다. 깨어나는 대기 스레드의 수(하나 대 전체)로 인해 또 다른 질문이 제기됩니다.

왜 하나의 스레드는 항상 객체 잠금을 다시 획득합니까?

일반적으로 이 경우, inform() 및 informAll()은 잠금을 다시 획득하기 위해 선택될 대기 스레드를 지정하지 않습니다. JVM 또는 시스템 스레드 스케줄러가 이 선택을 수행하며 이는 비결정적일 수 있습니다.

notifyAll()의 필요성

그러나 특정 시나리오에서는 inform()을 사용합니다. 다음 예와 같이 교착 상태가 발생할 수 있습니다.

notify()가 있는 Producer/Consumer 클래스

public class ProducerConsumer {

    private final int MAX_SIZE = 1;  // Buffer size

    private List buf = new ArrayList();

    public synchronized void put(Object o) {
        while (buf.size() == MAX_SIZE) {
            wait();
        }
        buf.add(o);
        notify();
    }

    public synchronized Object get() {
        while (buf.size() == 0) {
            wait();
        }
        Object o = buf.remove(0);
        notify();
        return o;
    }
}

교착 상태 시나리오:

  1. 생산자 P1이 개체를 버퍼에 넣습니다.
  2. 생산자 P2와 P3이 개체를 넣으려고 시도했지만 버퍼가 가득 차서 차단되었습니다.
  3. 소비자 C1이 버퍼에서 객체를 가져오려고 시도합니다.
  4. C1이 실행 중이고 객체를 가져온 다음 대기 스레드에 알립니다.
  5. P2 또는 C2는 알림에 의해 깨어날 수 있지만 잠금을 다시 획득하려는 시도가 둘 다 차단됩니다.
  6. C3도 잠금을 획득하려는 시도가 차단됩니다.

결과적으로 세 스레드 모두 무기한 대기하여 교착 상태가 발생합니다.

해결책: informAll()

이 교착 상태를 해결하려면 대신에 informAll()을 사용해야 합니다. 생산자/소비자 코드의 inform(). 이렇게 하면 대기 중인 모든 스레드가 활성화되어 교착 상태가 방지됩니다.

권장 사항:

대부분의 시나리오에서는 잠재적인 교착 상태를 방지하기 때문에 informAll()이 선호되는 방법입니다. 특정 시나리오에서 하나의 특정 대기 스레드만 깨워야 하는 경우에는 inform()을 주의해서 사용할 수 있습니다.

최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3