Vendo várias perguntas relacionadas ao bloqueio e (quase) sempre encontrando o 'loop por causa de termos de ativação espúrios' 1 Gostaria de saber se alguém experimentou esse tipo de ativação (assumindo um ambiente decente de hardware / software, por exemplo)?
Sei que o termo "espúrio" significa que não há razão aparente, mas quais podem ser as razões para esse tipo de evento?
( 1 Nota: não estou questionando a prática de loop.)
Edit: Uma pergunta auxiliar (para quem gosta de amostras de código):
Se eu tenho o seguinte programa e o executo:
public class Spurious {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
lock.lock();
try {
try {
cond.await();
System.out.println("Spurious wakeup!");
} catch (InterruptedException ex) {
System.out.println("Just a regular interrupt.");
}
} finally {
lock.unlock();
}
}
}
O que posso fazer para acordar await
espúria sem esperar eternamente por um evento aleatório?
java
multithreading
locking
spurious-wakeup
akarnokd
fonte
fonte
pthread_cond_wait()
a pergunta real é "Por que pthread_cond_wait tem ativações espúrias?" .Respostas:
O artigo da Wikipedia sobre despertares espúrios tem este boato:
Resumo : Se um processo Linux for sinalizado, seus threads em espera terão uma ativação agradável e quente e espúria .
Eu comprei isso. É uma pílula mais fácil de engolir do que a razão normalmente vaga de "é para desempenho".
fonte
futex()
chamada subjacente retornaEINTR
, mas esse valor de retorno não é alterado para o próximo nível. O chamador pthread deve, portanto, verificar se há invariável. O que eles estão dizendo é que, quandopthread_cond_wait()
retorna, você deve verificar sua condição de loop (invariável) novamente, porque a espera pode ter sido espúriamente acordada. Receber um sinal durante uma chamada do sistema é uma causa possível, mas não é a única.pthread
biblioteca poderia fornecer sua própria lógica invariável e sua própria verificação, a fim de eliminar despertares espúrios, em vez de passar essa responsabilidade para o usuário. Presumivelmente, isso teria o impacto reivindicado no desempenho.Eu tenho um sistema de produção que exibe esse comportamento. Um encadeamento aguarda um sinal de que há uma mensagem na fila. Nos períodos de maior movimento, até 20% das ativações são falsas (ou seja, quando acorda, não há nada na fila). Esse encadeamento é o único consumidor das mensagens. É executado em uma caixa com 8 processadores Linux SLES-10 e é construído com o GCC 4.1.2. As mensagens vêm de uma fonte externa e são processadas de forma assíncrona porque há problemas se o meu sistema não as lê com rapidez suficiente.
fonte
Para responder à pergunta do título - Sim! Embora o artigo do Wiki mencione muito sobre despertos espúrios, uma boa explicação para o mesmo que me deparei é a seguinte:
Eu estava lendo esta resposta da Source e achei razoável o suficiente. Leia também
Acordos espúrios em Java e como evitá-los .
PS: O link acima é para o meu blog pessoal, com detalhes adicionais sobre despertares espúrios.
fonte
Um tempo atrás, Cameron Purdy escreveu um post no blog sobre ser atingido pelo espúrio problema de ativação. Então sim, acontece
Suponho que esteja na especificação (como uma possibilidade) devido às limitações de algumas das plataformas nas quais o Java é implantado? embora eu possa estar errado!
fonte
Apenas para adicionar isso. Sim, isso aconteceu e passei três dias pesquisando a causa de um problema de multiencadeamento em uma máquina de 24 núcleos (JDK 6). 4 de 10 execuções experimentaram isso sem nenhum padrão. Isso nunca aconteceu em 2 ou 8 núcleos.
Estudou algum material on-line e esse não é um problema de Java, mas um comportamento geral raro, mas esperado.
fonte
https://stackoverflow.com/a/1461956/14731 contém uma excelente explicação de por que você precisa se proteger contra ativações espúrias, mesmo se o sistema operacional subjacente não as acionar. É interessante notar que esta explicação se aplica a várias linguagens de programação, incluindo Java.
fonte
Respondendo à pergunta do OP
, nenhuma ativação espúria poderia ativar esse segmento em espera!
Independentemente de as ativações espúrias poderem ou não acontecer em uma plataforma específica, em um caso do snippet do OP, é positivamente impossível para
Condition.await()
retornar e ver a linha "despertar espúrias!" no fluxo de saída.A menos que você esteja usando uma Java Class Library muito exótica
Isso ocorre porque standard, OpenJDK 's
ReentrantLock
método' snewCondition()
retorna aAbstractQueuedSynchronizer
'implementação s deCondition
interface, aninhadaConditionObject
(a propósito, é a única implementação daCondition
interface, neste biblioteca de classes), eoConditionObject
' s métodoawait()
em si verifica se a condição não espera e nenhuma ativação espúria pode forçar esse método a retornar por engano.A propósito, você pode verificar por si próprio, pois é muito fácil imitar a ativação espúria, uma vez que a
AbstractQueuedSynchronizer
implementação baseada em está envolvida.AbstractQueuedSynchronizer
usa baixo nívelLockSupport
'spark
eunpark
métodos, e se você invocarLockSupport.unpark
em um thread aguardando emCondition
, esta ação não pode ser distinguido de um despertar espúria.Refatorando levemente o snippet do OP,
, e não importa o quanto o encadeamento (principal) não-estacionário tentaria ativar o encadeamento em espera, o
Condition.await()
método nunca retornará nesse caso.Os despertares espúrios
Condition
dos métodos em espera são discutidos no javadoc daCondition
interface . Embora diga isso,e essa
mas depois acrescenta que
e
AbstractQueuedSynchronizer
a implementação daCondition
interface faz exatamente isso - remove qualquer possibilidade de despertares espúrios .Isso certamente vale para os outros
ConditionObject
métodos que aguardam.Então, a conclusão é:
devemos sempre chamar
Condition.await
no loop e verificar se a condição não se mantém, mas com o OpenJDK padrão, o Java Class Library nunca pode acontecer . A menos que, novamente, você use Java Class Library muito incomum (o que deve ser muito incomum, porque outras bibliotecas de classes Java não OpenJDK conhecidas, atualmente quase extintas GNU Classpath e Apache Harmony , parecem ter idênticas à implementação padrão daCondition
interface)fonte