2017-02-10 11 views
0

:이 부울을 확인하고 대기 내 쓰기 방법원자 부울 사용은 나는 다음과 같은 코드를 실행하려고

Atomic Boolean isChannelActive = new AtomicBoolean(false); 

: 내 생성자에서

내가 내 원자 부울 initalize

public ChannelFuture write(ByteBuf msgBuf) { 
if (!isChannelActive.get()) { 
    try { 
    wait(); 
    } catch (InterruptedException ex) { 
    logger.Error("Waiting interrupted", ex); 
    } 
} 

그러나 프로그램에있을 때 문제는이 원자 부울은 시간에 다른 스레드에서 설정 될 수있다 :

if (!isChannelActive.get()) { 
    try{ --- Right on here and program made a context switch at this time. 
    wait() 

이 시나리오에서는 내 부울 값이 true이고 notifyAll() 이벤트가 누락되어 컨텍스트 전환으로 인해 영원히 대기합니다.

이 문제를 어떻게 방지 할 수 있습니까?

나는 동기화 된 블록이 옵션 일 수 있지만이 경우에는 좀 더 우아한 옵션을 찾고 있음을 알고 있습니다.

+0

'대기()'를 호출하는 경우 이미 ** 동기화 된 상태입니다 **. – Kayaman

+0

[조건] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html)이 대안이 될 수 있습니까? – Fildor

+0

또한 CountdownLatch 메커니즘을 다시 한 번 살펴보고 잘 작동합니다. [CountdownLatches] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)에서 동일한 문제가 발생할 수 있습니다. –

답변

2

서로 다른 레벨의 동기화 메커니즘을 혼합해서는 안됩니다.

  1. wait/notify - 이것은 더 이상 사용할 필요가없는 고풍 시스템입니다. wait/notify으로 할 수있는 모든 작업은 synchronized 또는 Lock으로 수행 할 수 있습니다.

  2. synchronized - 이렇게하면 독점적 액세스가 필요한 섹션이 서로 간섭하지 않도록 코드를 동기화 할 수 있습니다.

  3. Lock s - 거의 모든 액세스 제어를 일반적으로 처리 할 수있는 다양한 유형의 잠금이 있습니다.

  4. Blocking... - 더 현대적인 접근 방식입니다. 데이터 구조를 사용하여 코드에 동기화를 넣는 대신 안전한 액세스를 보장합니다.

  5. 더 일반적인 메커니즘 중 일부를 달성하는 데 사용할 수있는 PhaserSemaphore과 같은 추가 기능 집합이 있습니다.

당신은 같은 시간에 atomicswait/notify를 사용하는 attemptin된다. 이것은 어려움 없이는 작동하지 않습니다.

아마도 Lock이 필요합니다.

Lock channelActive = new ReentrantLock(); 

public void test() { 
    channelActive.lock(); 
    try { 
     // Do your exclusive stuff here. 
    } finally { 
     channelActive.unlock(); 
    } 

} 
2

wait()으로 전화하는 경우 이미 인 경우 synchronized 블록입니다. 사용자 시나리오는 wait()notifyAll()을 호출하는 두 스레드가 동일한 개체 모니터를 가져와야하기 때문에 가상의 시나리오입니다.

따라서 [1] (이)라고 주장하는 곳에서 상황 전환이 불가능합니다. 여기에 AtomicBoolean을 사용하면 아무런 이점도 없습니다 (적어도 표시된대로) volatile boolean은 잘 작동합니다.

[1] 조건부 검사가 동기화 된 블록 외부에 있도록 코드를 작성할 수는 있지만 의도적으로 깨진 동시 코드를 작성하게됩니다.