Um bloqueio é necessário em uma situação em que o thread 1 verifica se um bool mudou de False para True periodicamente dentro de um loop, sendo o bool atualizado no thread 2?
Pelo que entendi, um bool é atômico em python, não deve ser possível que o bool seja atualizado incorretamente ou assuma um valor lixo como em C++, por exemplo. Apenas um thread atualizará o bool, e ele só irá de False para True (não há posição em que ele volte para False). Como a verificação é feita periodicamente e o tempo não é crítico, mesmo que o thread 1 leia o valor antigo (False) enquanto o thread 2 o estiver atualizando para True, o thread 1 ainda deve ser capaz de ler o novo valor assim que o thread 2 terminar a próxima iteração do loop.
Essa é uma compreensão incorreta dessa situação específica? Eu entendo que geralmente é melhor usar locks, e não me importo em adicionar um, mas me pergunto se isso seria apenas introduzir mais problemas em potencial (como deadlocks) sem realmente resolver nenhum problema, exceto talvez salvar o thread 1 de ficar em loop por mais uma iteração.
Este é o loop em questão. As duas variáveis estão sendo atualizadas em outro thread, e lidas neste. Ambos são valores bool começando como False e sendo definidos como True quando os outros threads terminaram.
while True:
time.sleep(0.2)
if self.joined_queries:
self.stop()
break
if self.timeout:
self.stop()
break
Houve alguns outros tópicos, mas as respostas foram muito gerais, sem entrar muito em detalhes, e a situação foi um pouco diferente. Gostaria de entender por que isso é uma má ideia ou não!
Este pedaço de documentação me faz acreditar que não é um problema, mas não tenho certeza se estou interpretando corretamente: http://www.python.org/doc/faq/library/#what-kinds-of-global-value-mutation-are-thread-safe
Na prática, uma variável bool em cPython será um ponteiro para um dos dois objetos
Py_True
ouPy_False
. Os detalhes de implementação não devem importar, mas é relevante saber que um bool em Python será exatamente tão atômico quanto um ponteiro em C.Em uma compilação cPython sem o GIL, isso será uma corrida de dados e, portanto, um comportamento indefinido de acordo com o código C subjacente.
A página que você linkou diz explicitamente que esse tipo de código é seguro devido ao GIL e que o trabalho de remoção do GIL para melhorar o desempenho está em andamento. Parece imprudente escrever um novo código que dependa dele.
Note que o Undefined Behaviour de C pode ser perfeitamente bem definido em uma determinada plataforma de hardware, mas não é portável. No entanto, o código será frágil diante de interpretadores e plataformas mais novos.