문제

나는 식당 철학자 문제에서 세마포어의 기본적인 jist를 배우려고 노력하고 있습니다. 지금은 클래스 젓가락이 있으며 각 젓가락은 1 개의 사용 가능한 허가가있는 세마포어가 있습니다.

public class Chopstick
{
    Thread holder = null;
    private Semaphore lock = new Semaphore(1);

    public synchronized void take() throws InterruptedException
    {
        this.lock.acquire();
        holder = Thread.currentThread();

    }

    public synchronized void release()
    {   
        this.lock.release();
        holder = null;
    }
}

홀더 변수는 필요한 기능에 사용됩니다.

public synchronized void conditionalRelease()
{
    if (holder == Thread.currentThread())
    {
        holder = null;
        this.lock.release();
    }
}

프로그램은 컴파일 및 실행되지만 젓가락을 풀어주는 데 어려움이있는 것 같습니다. 때로는 젓가락이 풀리며 때로는 그렇지 않습니다. 그들이 출시되지 않으면, 모든 젓가락이 취해지고 한 명의 철학자가 배가 고프면 프로그램이 결국 끊어집니다.

다음은 철학자 클래스 내의 코드가 임의의 시간 후에 젓가락을 출시하기위한 것입니다.

System.out.println(this.name + " is eating");
Thread.sleep(this.getRandTime());
System.out.println(this.name + " has finished eating");

rightChopstick.release();
System.out.println(this.name + " has released the right chopstick");
leftChopstick.release();
System.out.println(this.name + " has released the left chopstick");

내 프로그램은 예를 들어 "Philosopher 0이 식사를 마쳤습니다"를 출력하고 계속 실행을합니다. 다른 두 줄은 결코 출력하지 않기 때문에 분명히 내가 풀어주는 방식에 문제가 있습니다.

모든 도움이 감사합니다.

도움이 되었습니까?

해결책

메소드 서명에서 '동기화 된'키워드를 제거합니다. 외부 잠금 장치 (세마포어,이 경우)를 사용하고 있습니다. 'Synchronized'키워드는 객체 자체의 뮤텍스를 사용하여 잠금을 얻으려고합니다. 당신은 이제 내가 교착 상태를 일으킬 수 있다고 생각하는 2 개의 리소스를 잠그고 있습니다.

다른 팁

문제는 Thread1이 특정 젓가락을 가지고 있고 다른 젓가락이 같은 것을 얻으려고 할 때 take()-줄을 제외하고 this.lock.acquire(); 그러나 그것은 할 것입니다 아니다 객체 자체의 모니터를 해제하십시오.

이제 Thread1이 젓가락을 해제하려고한다면 입력 할 수 없습니다. release()-다른 스레드에 의해 여전히 잠겨 있기 때문에 method take(). 교착 상태입니다

젓가락에 잠그고 크기 1의 세마포어를 보유하고 있다는 것은 약간 혼란스러워 보입니다. 일반적으로 세마포어는 리소스에 대한 티켓을 제공하며 티켓이 하나만있는 경우 잠금과 동일한 효과적으로 배제됩니다 (잠금과 동일합니다). 동기화 된 블록 또는 잠금 객체). 실제로 젓가락을 잠금 물체 자체로 만드는 것을 고려할 수 있습니다.

나는 다른 전략을 사용하여 교착 상태를 피하는 방법에 관한 것이지만, 관심이 있으시면 Java의 식당 철학자들에 대한 블로그 게시물을했습니다.

잠금 또는 동기화 된 키워드가 사용되지 않도록하십시오. Chop Stick의 아래 코드는 나에게 잘 작동합니다. Pro가 아니라 아이디어를 주어야합니다.

public class Chopstick {
private boolean inuse;
Semaphore sem;

public Chopstick(){

    inuse = false;
    sem = new Semaphore(1);
}
public void pickUp()
{
    try
    {
        while(inuse)
        {
            try
            {
                sem.acquire();

            }
            catch(InterruptedException e) {}
        }
        inuse = true;
    }catch(Exception e){}
}
public void putDown()
{
    try
    {
        inuse = false;
        sem.release();

    }
    catch (Exception e){}
}

}

Philopser는 식사를 시작하기 전에 두 Chostick에 잠금 장치를 획득해야하며 Leftone을 먼저 픽업 한 다음 바로 기다려서 식사를 시작하여 시작 방법이 동기화되어야합니다. 다음 방법은 다음과 같이 작동합니다.

public synchronized void startEating() {
    leftChopstick.acquire();
    rightChopstick.acquire();
}

public void finishEating(int id) {
    leftChopstick.release();
    rightChopstick.release();
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top