대기 장면
일반적인 대기 전신 장면은 일반적으로 다음 두 내용과 관련이 있습니다.
1. 상태 변수
스레드가 대기 해야하는 경우 항상 일부 조건으로 인해 발생합니다. 예를 들어, 큐를 채우면 큐 요소가 가득 차면 스레드가 실행을 중지해야합니다. 대기열 요소가 비어 있으면 자체 실행을 계속하십시오.
2. 조건 술어
스레드가 대기에 입력할지 또는 알림에서 깨어날 지 여부가 결정되면 상태 조건이 충족되는지 테스트해야합니다. 예를 들어, 큐에 요소를 추가하면 대기열이 가득 차 있으므로 다른 스레드가 큐에서 요소를 제거하면 대기열에 나머지 공간이있어 대기에 추가 할 수 있습니다. 실." 이 시점에서 요소를 기다리는 과정은 깨어나고 현재 대기열이 실제로 존재하는 경우 요소를 추가하십시오. 그렇지 않은 경우 계속 차단하고 기다리십시오. 다음 웨이크 -UP.
3. 조건 대기열
각 객체에는 객체의 대기 함수를 호출 할 때 각 객체에는 객체의 조건 대기열이 추가됩니다.
알아채다
대기 및 알림은 Java 동기화 메커니즘의 중요한 부분입니다. 동기화 된 키워드 사용과 결합하여 프로듀서 소비자 모델과 같은 많은 우수한 동기 모델을 설정할 수 있습니다. 그러나 function (), notify (), notifyall () 함수를 사용하는 경우 다음 사항에 특별한주의를 기울여야합니다.
대기 (), notify (), notifyall () 메소드는 스레드 클래스에 속하지 않지만 객체 기초 클래스에 속합니다. 각 객체가 잠겨 있으므로 잠금은 각 객체의 기초이므로 잠금 방법이 가장 기본적입니다.
OBJ의 대기 () 및 notify () 메소드를 호출하려면 OBJ 잠금을 가져와야합니다. 즉, 동기화 된 (OBJ) {...} 코드 세그먼트로 작성해야합니다.
Obj.wait ()을 호출 한 후 스레드 A는 OBJ의 잠금을 릴리스합니다. 그렇지 않으면 스레드 B는 OBJ 잠금을 얻을 수 없으며 동기화 된 (OBJ) {...} 코드에서 스레드 A를 깨울 수 없습니다. 분절.
obj.wait () 메소드가 돌아 오면 OBJ 잠금을 다시 가져와 실행을 계속해야합니다.
스레드 A1, A2, A3이 obj.wait ()에 있으면 스레드 B는 OBJ.Notify ()를 호출합니다.
스레드 B가 obj.notifyall ()을 호출하면 대기 스레드 A1, A2, A3을 모두 깨울 수 있지만 대기 스레드는 다음 문장을 계속 실행하여 obj.wait ()를 계속 실행해야합니다. 따라서 스레드 A1, A2, A3은 잠금을 얻을 수있는 기회가 한 번 뿐이며 A1은 계속 실행되기 전에 A1이 OBJ 잠금을 풀기까지 기다려야합니다.
스레드 B가 obj.notify () 또는 obj.notifyall ()을 호출하면 스레드 B가 OBJ 잠금을 보유하고 있지만 스레드 A1, A2, A3은 깨어납니다. 스레드 B가 동기화 된 코드 블록을 종료하고 OBJ 잠금을 해제 할 때까지 스레드 A1, A2, A3의 하나는 객체 잠금을 가져와 계속 실행할 수 있습니다.
예를 들어 코드
스레드 대기 작업의 일반적인 코드 구조는 다음과 같습니다.
public void test ()는 InterruptedException {synchronized (obj) {while (! contidition) {obj.wait ();}}}}}}}}을 던집니다.
OBJ.Wait () 작업이주기에 있어야하는 이유는 무엇입니까? 몇 가지 주요 이유가 있습니다.
1. 객체 잠금은 여러 상태 변수를 모두 대기하지 않으면 대기 시간을 대기하지 않으면 문제가 발생할 수 있습니다. 예를 들어, 특정 객체는 A와 B를 보호하기 위해 OBJ를 잠그고 ASSERTION의 조건이 설정되지 않으면 대기 조건이 큐에서 발생합니다. 이제 상태 변수 A의 작동이 발생하면 OBJ에서 NotifyAll 작업이 호출되면 OBJ에 해당하는 조건 대기열의 모든 스레드가 깨어납니다. 현재 B가 깨어나므로 B의 상태가 충족 될지 여부를 재활용해야합니다.
2. 다중 스레드의 동일한 상태의 조건이 주장된다. 예를 들어, 큐에 요소를 추가하는 장면, 현재 대기열이 가득 차고 여러 스레드가 내부에 요소를 추가하려고하므로 모두 이루어집니다. 현재 다른 스레드는 대기열에서 요소를 꺼내어 모든 스레드를 깨우기 위해 NotifyAll 작업을 호출했지만 다른 스레드만이 큐에 추가 할 수 있습니다.
3. 거짓 깨우기. 통지를받지 않고 인터럽트 오라우트를 사용하면 스레드가 자동으로 깨어났습니다. 이 상황은 실제로 거의 발생하지 않지만,이 상황은주기 대기를 통해 제거 될 수 있습니다.