Por que não é possível construir semáforo binário com if dentro em Java

votos
0

Eu tenho uma pequena pergunta que me deixa um pouco confuso.

Este é meu código:

public synchronized void P() {
    while(!_state) {
        this.wait();
    }
    _state = false;
}

Este método é responsável por tomar semáforo. Por que não é possível construir semáforo binário com ifdeclaração em vez de whileloop?

O docs oráculo diz:

Em primeiro lugar, não é possível para dois invocações de métodos sincronizadas no mesmo objecto a intercalação. Quando uma linha é a execução de um método sincronizado para um objecto, todos os outros segmentos que invocam métodos sincronizados para o mesmo bloco de objecto (suspender a execução) até que o primeiro segmento é feito com o objeto.

Então, exatamente apenas um segmento deve ser dentro do método P () -> tão somente um segmento deve ser bloqueado em espera () método. Resto de fios deve ser bloqueado no nível do método P (). Mas quando eu estou substituindo while()por if()ele não funciona adequadamente

Publicado 20/10/2018 em 13:58
fonte usuário
Em outras línguas...                            


2 respostas

votos
0

Por que não é possível construir semáforo binário com ifdeclaração em vez de whileloop?

Para uma resposta mais profunda, você deve trabalhar através da Oracle tutorial vigiado Blocks .

A resposta mais curta é, há um par de razões pelas quais _statepoderia ser falsequando a wait()chamada retorna:

  1. Vários consumidores: Geralmente é mais seguro para acordar dorminhocos com notifyAll()em vez de notify(), e se você escrever um programa em que dois ou mais threads poderia chamar a P()função, você provavelmente só querem um deles para ser autorizado a proceder quando algum outro thread chama a V()função . Então, se todos eles "acordar", você vai querer apenas um para configurar _state=false;e você vai querer que os outros para voltar a dormir.

  2. O mesmo objeto está recebendo notifyAll()chamadas por mais de uma razão. Não é uma boa prática, mas isso acontece, especialmente em projetos onde muitos desenvolvedores contribuem para o código. Nesse caso, você não wan a P()chamada para retornar se o objeto foi notificada pelo motivo errado. Você quer isso para voltar e continuar de espera.

  3. A documentação para o.wait()diz que ele está autorizado a regressar, mesmo quando o objeto onão foi notificado em tudo. Isto é conhecido como "despertar espúria." Isso acontece raramente, e apenas em alguns sistemas operacionais, mas eles permitem-lo porque ele permite uma implementação mais eficiente de wait()e notify().

Respondeu 20/10/2018 em 15:55
fonte usuário

votos
0

synchronizedmétodo é equivalente a synchronized(this)bloquear.

Apenas um segmento é permitida a entrada de bloco sincronizado. Ao entrar, aquires rosca bloquear. Quando você waitdentro de blocos de sincronização, você liberar o bloqueio (monitor objeto) e estacionar o segmento atual. Neste momento, outro segmento é permitido entrar nesse bloco. Execução continuará quando outro segmento irá chamar notifyou notifyAllno mesmo objeto que waitfoi invocado. Fio notificada "estado saída de espera" quando o bloqueio determinado bloco de sincronização será lançado.

Para resumir - espera não funciona como você espera, não bloquear a execução, só coloca esperando thread para dormir, permitindo que outros segmentos para adquirir bloqueio sincronia.

Então você não pode fazer o que você quer alcançar, porque waitfunciona de forma diferente, então você esperar. O que você quer para usar aqui, é ReentrantLock. https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html

Respondeu 20/10/2018 em 14:12
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more