Nota: sempre que menciono, thread
quero dizer especificamente threads em python até que seja explicitamente declarado.
Threads funcionam de maneira um pouco diferente em python se você estiver vindo de C/C++
segundo plano. No python, apenas um thread pode estar em execução em um determinado momento. Isso significa que os threads no python não podem realmente aproveitar o poder de vários núcleos de processamento, pois, por design, não é possível que os threads sejam executados paralelamente em vários núcleos.
Como o gerenciamento de memória em python não é seguro para threads, cada thread requer um acesso exclusivo às estruturas de dados no interpretador python. Esse acesso exclusivo é adquirido por um mecanismo chamado (bloqueio global do interpretador) .GIL
Why does python use GIL?
A fim de evitar que vários threads acessem o estado do interpretador simultaneamente e corrompam o estado do interpretador.
A ideia é sempre que um thread está sendo executado (mesmo que seja o thread principal) , um GIL é adquirido e após algum intervalo de tempo predefinido o GIL é liberado pelo thread atual e readquirido por algum outro thread (se houver).
Why not simply remove GIL?
Não que seja impossível remover o GIL, é apenas que, no processo de fazer isso, acabamos colocando vários bloqueios dentro do interpretador para serializar o acesso, o que torna até mesmo um único aplicativo encadeado menos performante.
portanto, o custo de remoção do GIL é compensado pela redução do desempenho de um aplicativo thread único, o que nunca é desejado.
So when does thread switching occurs in python?
A troca de thread ocorre quando GIL é lançado. Então, quando GIL é lançado? Existem dois cenários a serem considerados.
Se um Thread estiver fazendo operações vinculadas à CPU (processamento de imagem Ex).
Em versões mais antigas do python, a troca de thread costumava ocorrer após um não fixo de instruções do python. Por padrão, era definido como 100
. Descobriu-se que não é uma política muito boa decidir quando a troca deve ocorrer, pois o tempo gasto na execução de uma única instrução pode ir de milissegundo até mesmo um segundo. Portanto, liberar GIL após todas as 100
instruções, independentemente do tempo que levem para executar, é uma política ruim.
Em novas versões, em vez de usar a contagem de instruções como uma métrica para alternar o thread, um intervalo de tempo configurável é usado. O intervalo de troca padrão é de 5 milissegundos. Você pode obter o intervalo de troca atual usando sys.getswitchinterval()
. Isso pode ser alterado usandosys.setswitchinterval()
Se um thread está fazendo algumas operações vinculadas de IO (acesso ao sistema de arquivos Ex ou
IO de rede)
GIL é liberado sempre que o thread está aguardando a conclusão de alguma operação de E / S.
Which thread to switch to next?
O intérprete não tem seu próprio agendador. Qual thread é agendado no final do intervalo é uma decisão do sistema operacional. .