> Java > java지도 시간 > 본문

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

Mary-Kate Olsen
풀어 주다: 2024-11-24 11:38:10
원래의
388명이 탐색했습니다.

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

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

notify()와 informAll()의 주요 차이점은 깨어나는 대기 스레드의 수(하나 대 전체)는 또 다른 질문을 제기합니다.

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

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

notifyAll()의 필요성

그러나 특정 시나리오에서는 inform()을 사용합니다. 다음 예에서 설명한 것처럼 교착 상태로 이어질 수 있습니다.

생산자/소비자 클래스 통지()

public class ProducerConsumer {

    private final int MAX_SIZE = 1;  // Buffer size

    private List<Object> 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()

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

권장 사항:

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

위 내용은 한 스레드가 통지() 또는 통지All() 후에 항상 객체 잠금을 다시 획득하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿