Dominando a comunicação entre threads em Python:sincronização e compartilhamento de dados
Comunicação entre threads refere-se ao processo de permitir a comunicação e sincronização entre threads em um programa Python multithread.
Geralmente, threads em Python compartilham o mesmo espaço de memória dentro de um processo, o que lhes permite trocar dados e coordenar suas atividades por meio de variáveis compartilhadas, objetos e mecanismos de sincronização especializados fornecidos pelo módulo de threading.
Para facilitar a comunicação entre threads, o módulo de threading fornece várias primitivas de sincronização, como objetos Locks, Events, Conditions e Semáforos. Neste tutorial você aprenderá como usar o objeto Event e Condition para fornecer a comunicação entre threads em um programa multithread.
O objeto de evento
Um objeto Event gerencia o estado de um sinalizador interno para que os threads possam esperar ou definir. O objeto Event fornece métodos para controlar o estado desse sinalizador, permitindo que threads sincronizem suas atividades com base em condições compartilhadas.
O sinalizador é inicialmente falso e se torna verdadeiro com o método set() e redefinido para falso com o método clear(). O método wait() é bloqueado até que o sinalizador seja verdadeiro.
A seguir estão os principais métodos do objeto Event -
- is_set():Retorna True se e somente se o sinalizador interno for verdadeiro.
- set():Defina o sinalizador interno como verdadeiro. Todos os threads que esperam que isso se torne realidade são despertados. Threads que chamam wait() quando o sinalizador é verdadeiro não serão bloqueados.
- clear():redefine o sinalizador interno para falso. Posteriormente, os threads que chamam wait() serão bloqueados até que set() seja chamado para definir o sinalizador interno como verdadeiro novamente.
- wait(timeout=None):Bloqueia até que o sinalizador interno seja verdadeiro. Se o sinalizador interno for verdadeiro na entrada, retorne imediatamente. Caso contrário, bloqueie até que outro thread chame set() para definir o sinalizador como verdadeiro ou até que ocorra o tempo limite opcional. Quando o argumento timeout estiver presente e não None, ele deverá ser um número de ponto flutuante especificando um tempo limite para a operação em segundos.
Exemplo
O código a seguir tenta simular o fluxo de tráfego sendo controlado pelo estado do semáforo VERDE ou VERMELHO.
Existem dois threads no programa, visando duas funções diferentes. A função signal_state() ativa e zera periodicamente o evento indicando mudança de sinal de VERDE para VERMELHO.
A função tráfego_flow() espera que o evento seja definido e executa um loop até que ele permaneça definido.
04Saída
Ao executar o código acima, você obterá a seguinte saída -
13O objeto de condição
O objeto Condition no módulo threading do Python fornece um mecanismo de sincronização mais avançado. Ele permite que threads aguardem uma notificação de outro thread antes de prosseguir. Os objetos Condition estão sempre associados a um bloqueio e fornecem mecanismos de sinalização entre threads.
A seguir está a sintaxe da classe threading.Condition() -
21
Abaixo estão os principais métodos do objeto Condition -
- acquire(*args):adquire o bloqueio subjacente. Este método chama o método correspondente no bloqueio subjacente; o valor de retorno é o que o método retorna.
- release():libera o bloqueio subjacente. Este método chama o método correspondente no bloqueio subjacente; não há valor de retorno.
- wait(timeout=None):Este método libera o bloqueio subjacente e, em seguida, bloqueia até que ele seja despertado por uma chamada notify() ou notify_all() para a mesma variável de condição em outro thread, ou até que o tempo limite opcional ocorra. Uma vez despertado ou expirado, ele readquire o bloqueio e retorna.
- wait_for(predicate, timeout=None):Este método utilitário pode chamar wait() repetidamente até que o predicado seja satisfeito ou até que ocorra um tempo limite. O valor de retorno é o último valor de retorno do predicado e será avaliado como False se o tempo limite do método expirar.
- notify(n=1):Este método desperta no máximo n threads aguardando a variável de condição; é autônomo se nenhum thread estiver esperando.
- notify_all():ativa todos os threads que aguardam nesta condição. Este método funciona como notify(), mas ativa todos os threads em espera em vez de um. Se o thread de chamada não tiver adquirido o bloqueio quando este método for chamado, um RuntimeError será gerado.
Exemplo
Este exemplo demonstra uma forma simples de comunicação entre threads usando o objeto Condition do módulo threading do Python. Aqui thread_a e thread_b são comunicados usando um objeto Condition, o thread_a espera até receber uma notificação de thread_b. o thread_b dorme por 2 segundos antes de notificar o thread_a e depois termina.
35
Saída
Ao executar o código acima, você obterá a seguinte saída -
43Exemplo
Aqui está outro código que demonstra como o objeto Condition é usado para fornecer a comunicação entre threads. Neste, o thread t2 executa a função taskB() e o thread t1 executa a função taskA(). O thread t1 adquire a condição e a notifica.
Nesse momento, o thread t2 está em estado de espera. Depois que a condição é liberada, o thread em espera consome o número aleatório gerado pela função de notificação.
51
Quando você executa este código, ele produzirá a seguinte saída -
64
Explorando classes e objetos anônimos em Python Domine a metaprogramação em Python:técnicas avançadas de metaclasse
python
- Python retorna vários valores
- Data e hora do Python
- O Zen of Python (easter egg PEP-20)
- Python TUPLE – Pack, Unpack, Compare, Slicing, Delete, Key
- Python - Programação GUI (Tkinter)
- Python - Loops
- Verifique sua versão do Python no Linux, macOS e Windows:um guia rápido
- DSLs Python:soluções sob medida para domínios especializados
- Python - Expressões Regulares
- Lista Python