2013-04-14 2 views
0

새 조건 chopstickFree을 만들었습니다. 내 pickUpChopstick() 메서드에서 잠금을 기다리고 있지만 액세스 할 수 없습니다. 디버깅을 통해 Java - 재진입 성 잠금, 새로 생성 된 조건에 액세스 할 수 없습니다.

나는 그것이 pickUpChopstick() 방법에 chopstickFree.await() 라인에 도달 할 때, 그냥

이해가 안 무기한 일시 정지 것을 발견했다? 생성자의 해당 코드는 작동시키려는 확실하지 않은 시도 였지만 어떤 방식 으로든 새로운 조건을 만들었고 모든 것이 자유라는 신호를 보냈지 만 전혀 고정시킬 수는 없었습니다.

public class Chopstick { 
    Lock lock = new ReentrantLock(); 

    private Condition chopstickFree = lock.newCondition(); 
    private Condition chopstickInUse = lock.newCondition(); 

    Chopstick() { 
     lock.lock(); 
     chopstickFree.signalAll(); 
     lock.unlock(); 
    } 

    // Pick up chopstick 
    public void pickUpChopstick() throws InterruptedException { 
     lock.lock(); 

     try { 
      chopstickFree.await(); // ALWAYS PAUSES HERE INDEFINITELY 
      chopstickInUse.signalAll(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } finally { 
      lock.unlock(); 
     } 
    } 

    // Release chopstick 
    public void releaseChopstick() { 
     lock.lock(); 
     chopstickFree.signal(); 
     lock.unlock(); 
    } 
} 

아이디어가 있으십니까?

건배

+0

무한 정지 만 예외 없음 – mgibson

+1

'젓가락'의 두 가지 인스턴스가있을 가능성이 없으며 신호가 differe에게 발생하고 있습니다. 대기보다 인스턴스가 더 많습니까? – Gray

+0

흠 잘 ArrayList 이 있습니다. 두 개의 젓가락이 다른 클래스에 전달되었으며 그 클래스는 pickupLeftChopstick() 메서드를 사용했으며,이 메서드는 Chopstick 클래스의 pickUpChopstick() 메서드를 호출했습니다. – mgibson

답변

2

Condition#signalAll()Condition#await() (또는 친구)에 현재 스레드, 즉 신호가 나중에 호출 대기하고 있지 않은 신호를 보낸다.

당신은 제대로 구현하기 위해 잠금 장치에 의해 보호되는 다른 플래그가 필요합니다

public class Chopstick { 
    private final Lock lock = new ReentrantLock(); 
    private final Condition chopstickFree = lock.newCondition(); 
    private volatile boolean isFree = true; 

    Chopstick() { /* Nothing */ } 

    // Pick up chopstick 
    public void pickUpChopstick() throws InterruptedException { 
    lock.lock(); 

    try { 
     while (!isFree) { 
     chopstickFree.await(); 
     } 
     isFree = false; 
    } finally { 
     lock.unlock(); 
    } 
    } 

    // Release chopstick 
    public void releaseChopstick() { 
    lock.lock(); 
    try { 
     isFree = true; 
     chopstickFree.signal(); 
    } finally { 
     lock.unlock(); 
    } 
    } 
} 
다음

사용 버전 인 Semaphore 원래 구현 의도에 좀 더 가까이있을 것을 :

public class Chopstick { 
    private final Semaphore chopsticksAvailable = new Semaphore(1); 

    Chopstick() { 
    // Nothing 
    } 

    // Pick up chopstick 
    public void pickUpChopstick() throws InterruptedException { 
    chopsticksAvailable.acquire(); 
    } 

    // Release chopstick 
    public void releaseChopstick() { 
    chopsticksAvailable.release(); 
    } 
} 
+0

감사합니다, 매우 도움이됩니다! – mgibson