Pergunta

Estou tentando aprender o jist básico de um semáforo no problema do filósofo para refeições. No momento, tenho uma variedade de pauzinhos de classe e cada pauzinho tem um semáforo com 1 licença disponível:

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;
    }
}

A variável do suporte é usada para uma função que não tenho certeza de que preciso:

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

O programa compila e executa, mas parece ter alguns problemas para liberar os pauzinhos. Às vezes, os pauzinhos são liberados, às vezes não. Quando eles não se liberam, o programa acaba desligando quando todos os pauzinhos são levados e um filósofo está com fome.

Aqui está o código da classe filósofaria para lançar o pauzinho após um período aleatório de tempo:

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");

Meu programa produz "filósofo 0 terminou de comer", por exemplo, e continua a execução. As outras duas linhas nunca saíram, então, obviamente, algo está errado com a maneira como estou lançando.

Qualquer ajuda é apreciada.

Foi útil?

Solução

Eu tiraria a palavra -chave 'sincronizada' das assinaturas de seu método. Você está usando um mecanismo de travamento externo (o semáforo, neste caso). A palavra -chave 'sincronizada' está tentando obter bloqueios usando o próprio mutex do objeto. Agora você está bloqueando 2 recursos que eu suspeito que possam estar causando um impasse.

Outras dicas

O problema é que, quando o thread1 tem um pauzinho específico e outro tenta obter o mesmo, ele vai esperar no take()-Metódico on -line this.lock.acquire(); mas vai NÃO Libere o monitor no próprio objeto.

Se agora Thread1 tenta liberar o pauzinho, ele não pode entrar no release()-Metódico, já que ainda está bloqueado pelo outro tópico esperando em take(). Isso é um impasse

Parece um pouco confuso que vocês dois estão bloqueando o pauzinho e mantê -lo um semáforo do tamanho 1. Geralmente, um semáforo fornece ingressos para um recurso e, se você tiver apenas um ingresso, isso é efetivamente exclusão mútua, idêntica a uma trava ( um bloco sincronizado ou um objeto de bloqueio). Você pode considerar realmente fazer do pauzinho o próprio objeto de trava.

Fiz uma postagem no blog sobre os filósofos de jantar em Java há algum tempo, se você estiver interessado, embora seja realmente sobre como evitar o impasse usando outras estratégias.

Verifique se não há nenhuma palavra -chave de bloqueio ou sincronizado usado. O código abaixo para o chop stick funciona bem para mim .. não é um profissional, mas deve te dar uma ideia;

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){}
}

}

O Filosffer precisa adquirir o bloqueio em ambos os Chosticks antes de começar a comer e pegará o Leforne primeiro e aguarde a direita, então comece a comer, para que o método de início deve ser sincronizado. Os métodos a seguir farão com que funcione:

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

public void finishEating(int id) {
    leftChopstick.release();
    rightChopstick.release();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top