OP의 질문에 답변
무작위 이벤트를 영원히 기다리지 않고이 대기를 깨우려면 어떻게해야합니까?
, 어떤 가짜 모닝콜 도이 기다리는 스레드를 깨울 수 없습니다 !
에 관계없이 의사를 깨우는가 또는 영업의의 경우, 특정 플랫폼에서 일어날 수 있는지 여부의는 긍정적이다 니펫을 불가능 에 대한 Condition.await()
반환하고 라인을보고 "가짜 웨이크 업!" 출력 스트림에서.
매우 이국적인 Java 클래스 라이브러리를 사용하지 않는 한
표준 때문이다 오픈 JDK 의 ReentrantLock
의 방법 newCondition()
반환 AbstractQueuedSynchronizer
'의의 구현 Condition
중첩 된 인터페이스, ConditionObject
(그런데, 그것의 유일한 구현 Condition
이 클래스 라이브러리 인터페이스), 그리고 ConditionObject
의 방법 await()
조건이되지 않습니다 여부를 자체 점검 보류하고 가짜 웨이크 업으로 인해이 메소드가 실수로 리턴되지 않을 수 있습니다.
그건 그렇고, 일단 AbstractQueuedSynchronizer
기반 구현이 포함 되면 가짜 모닝콜을 모방하기가 쉽기 때문에 직접 확인할 수 있습니다 .
AbstractQueuedSynchronizer
낮은 수준의 사용 LockSupport
의 park
와 unpark
방법, 그리고 경우에있는 invoke LockSupport.unpark
에 대기중인 스레드에 Condition
,이 작업은 가짜 웨이크 업 구별 할 수 없습니다.
OP의 스 니펫을 약간 리팩토링
public class Spurious {
private static class AwaitingThread extends Thread {
@Override
public void run() {
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
lock.lock();
try {
try {
cond.await();
System.out.println("Spurious wakeup!");
} catch (InterruptedException ex) {
System.out.println("Just a regular interrupt.");
}
} finally {
lock.unlock();
}
}
}
private static final int AMOUNT_OF_SPURIOUS_WAKEUPS = 10;
public static void main(String[] args) throws InterruptedException {
Thread awaitingThread = new AwaitingThread();
awaitingThread.start();
Thread.sleep(10000);
for(int i =0 ; i < AMOUNT_OF_SPURIOUS_WAKEUPS; i++)
LockSupport.unpark(awaitingThread);
Thread.sleep(10000);
if (awaitingThread.isAlive())
System.out.println("Even after " + AMOUNT_OF_SPURIOUS_WAKEUPS + " \"spurious wakeups\" the Condition is stil awaiting");
else
System.out.println("You are using very unusual implementation of java.util.concurrent.locks.Condition");
}
}
unparking (main) 스레드가 대기중인 스레드를 깨우려고 시도해도 아무리 어려운 경우에도이 Condition.await()
메서드는 반환되지 않습니다.
Condition
대기중인 메소드 에 대한 가짜 깨우기 는 Condition
인터페이스 의 javadoc 에서 논의됩니다 . 그렇게 말하지만
조건을 기다릴 때 가짜 웨이크 업이 발생할 수 있습니다
그리고
응용 프로그램 프로그래머는 항상 발생할 수 있다고 가정하므로 항상 루프에서 기다리십시오.
하지만 나중에 추가합니다
가짜 웨이크 업 가능성을 제거하는 구현은 자유 롭다
그리고 인터페이스 AbstractQueuedSynchronizer
의 구현 은 스퓨리어스 웨이크 업의 가능성을 제거합니다 .Condition
이것은 다른 ConditionObject
대기중인 방법에 대해서도 마찬가지입니다 .
그래서, 결론은 다음과 같습니다
우리는 항상 Condition.await
루프를 호출 하고 조건이 유지되지 않는지 확인해야하지만 표준 OpenJDK를 사용하면 Java 클래스 라이브러리가 발생할 수 없습니다 . 다시 한 번, 매우 특이한 Java 클래스 라이브러리를 사용하지 않는 한 (현재 거의 멸종 된 GNU Classpath 및 Apache Harmony 로 알려진 다른 OpenJDK Java 클래스 라이브러리 는 표준 Condition
인터페이스의 표준 구현과 동일한 것으로 보이므로 매우 예외적 임 )
pthread_cond_wait()
실제 질문을 사용 하는 JVM의 경우 "pthread_cond_wait에 가짜 웨이크 업이 발생하는 이유는 무엇입니까?" .