A explicação de despertares espúrios soa como um bug que simplesmente não vale a pena consertar, certo?

30

De acordo com o artigo da Wikipedia sobre Spurious Wakeups

"um encadeamento pode ser despertado de seu estado de espera mesmo que nenhum encadeamento tenha sinalizado a variável de condição".

Embora eu saiba sobre esse 'recurso', nunca soube o que realmente o causou até, no mesmo artigo

"Acordos espúrios podem parecer estranhos, mas em alguns sistemas multiprocessadores, tornar o despertar de condições completamente previsível pode atrasar substancialmente todas as operações de variáveis ​​de condição".

Parece um bug que simplesmente não vale a pena consertar, não é mesmo?

James
fonte
11
related: "Por que pthread_cond_wait tem despertares espúrios?", stackoverflow.com/questions/8594591/…
Florian Castellane

Respostas:

39

A suposição TL; DR ("contrato") de ativações espúrias é uma decisão arquitetural sensata feita para permitir implementações realmente robustas do sheduler de encadeamentos.

As "considerações sobre desempenho" são irrelevantes aqui, são apenas mal-entendidos que se espalharam por terem sido declarados em uma referência oficial publicada. (as referências autoritativas podem ter erros, você sabe - basta perguntar ao Galileo Galilei ). O artigo da Wikipedia mantém a referência à nota que você citou, apenas porque combina perfeitamente com as diretrizes formais de citação da referência publicada.

Razões muito mais convincentes para a introdução do conceito de ativação espúria são fornecidas nesta resposta no SO, com base em detalhes adicionais fornecidos em uma (versão mais antiga) desse mesmo artigo:

O artigo da Wikipedia sobre despertares espúrios tem este boato:

A pthread_cond_wait()função no Linux é implementada usando a futexchamada do sistema. Cada chamada do sistema de bloqueio no Linux retorna abruptamente EINTRquando o processo recebe um sinal. ... pthread_cond_wait()não é possível reiniciar a espera porque pode perder uma ativação real no pouco tempo em que esteve fora da futexchamada do sistema ...

Basta pensar nisso ... como qualquer código, o agendador de threads pode sofrer um apagão temporário devido a algo anormal acontecendo no hardware / software subjacente. Obviamente, deve-se tomar cuidado para que isso aconteça o mais raro possível, mas como não existe software 100% robusto, é razoável supor que isso possa acontecer e tomar cuidado com a recuperação normal, caso o agendador detecte isso (por exemplo, observando batimentos cardíacos ausentes ).

Agora, como o agendador poderia se recuperar, levando em consideração que durante o blecaute poderia perder alguns sinais destinados a notificar threads em espera? Se o planejador não fizer nada, os encadeamentos "azarados" mencionados simplesmente travarão, aguardando para sempre - para evitar isso, o agendador simplesmente enviaria um sinal para todos os encadeamentos em espera.

Isso torna necessário estabelecer um "contrato" para que o thread em espera possa ser notificado sem um motivo. Para ser mais preciso, haveria um motivo - blecaute do planejador - mas como o encadeamento foi projetado (por um bom motivo) para não dar atenção aos detalhes de implementação interna do planejador, é provável que esse motivo seja melhor apresentado como "espúrio".


Da perspectiva do thread, isso se assemelha um pouco à lei de Postel (também conhecida como princípio da robustez ),

seja conservador no que faz, seja liberal no que aceita dos outros

A suposição de despertares espúrios força o encadeamento a ser conservador no que faz : definir condição ao notificar outros encadeamentos e liberal no que aceita : verifique a condição em qualquer retorno da espera e repita a espera se ainda não estiver lá.

mosquito
fonte
10
Ugh ... A lei de Postel ... a razão pela qual o HTML e todo tipo de tecnologia da Web têm tanta porcaria (por exemplo, aceitação do HTML de aninhamento incorreto de tags). Além disso, boa resposta.
Thomas Eding 30/10
3
A lei de Postel é a razão pela qual muitos erros não são detectados por anos, porque, mesmo que sua função retorne a saída errada, o aplicativo ainda parece funcionar! Melhor invenção de sempre.
Pacerier
2
@ Pacerier: a função que retorna uma saída errada não está seguindo a lei de Postel (parte conservadora).
precisa saber é o seguinte
@Pacerier: OTOH, exigir que outros componentes sejam rigorosos para que os erros possam ser detectados mais cedo é uma posição interessante, errando ao lado do princípio 'Fail Fast' e do design 'Contract Based'.
YvesgereY
1

Não vale a pena consertar, pois o código do chamador deve usar o mesmo tratamento (verificar a condição) de qualquer maneira, para lidar com a condição de corrida.

Um tratamento para dois problemas, que resumo do seguinte modo:

Ativação espúria: o encadeamento em espera é agendado antes que a condição seja estabelecida.
Suspensão forçada: o encadeamento em espera é agendado após a condição ser falsificada novamente.

Como o último pode acontecer, alguns chegaram ao ponto de introduzir um despertar espúrio no contrato:

  • para impor boas práticas exigindo loops de predicado.
  • para dar alguma liberdade à implementação do agendador (incluindo uma opção de recuperação de emergência, como apontado por @gnat).

Referência SO

YvesgereY
fonte
Eu gostaria de marcar com +1 isso, mas com a ideia de que alguém introduziu intencionalmente despertares espúrios para fazer com que os chamadores adicionem loops predicados para resolver excessos forçados. Eu acho isso inconcebível.
ruakh 04/01
'A intenção era forçar o código correto / robusto, exigindo loops de predicado.' Veja o link fornecido.
YvesgereY