Sim, eu havia parado de publicar aqui, mas do ponto de vista marketeiro é melhor continuar publicando... Seguimos.
:
:
.
A ideia do GIL é prevenir race conditions, que podem surgir quando mais de uma thread precisa referenciar um objeto Python ao mesmo tempo. Se mais de uma thread modificar uma variável compartilhada essa variável pode ficar em um estado inesperado. Imagem retirada do
Na imagem acima duas threads estão tentando incrementar uma reference count simultaneamente, e aí ao invés da contagem dar 2, já que as duas estão incrementando 1, o resultado final dá 1 (cada thread é uma coluna).
O que é concorrência?
Concorrência em computação acontece quando lida-se com mais de uma tarefas, sem necessariamente estar executando essas duas tarefas exatamente ao mesmo tempo. Uma frase conhecida do
O que é paralelismo?
Paralelismo significa que mais de uma task está sendo executada ao mesmo tempo. Em outras palavras, paralelismo implica concorrência (lidar com mais de uma task), mas concorrência não implica paralelismo (tasks não estão necessariamente sendo executadas em paralelo, ao mesmo tempo). Para que paralelismo seja possível precisamos de mais de um core de CPU.
No Python paralelismo é alcançado, por exemplo, com a lib multiprocessing, onde teremos mais de um processo Python, cada um com seu GIL. A imagem ajuda a ilustrar paralelismo em Python:
é uma lib para atingir concorrência usando o async e await. Pela documentação:
O asyncio é usado como uma base para várias estruturas assíncronas do Python que fornecem rede e servidores web de alto desempenho, bibliotecas de conexão de banco de dados, filas de tarefas distribuídas etc.
Como você pode imaginar, essa lib é adequada para otimizar tarefas I/O bound, onde temos tempo de espera de network, escrita em disco, etc. Numa operação CPU bound não há espera, dependemos apenas da velocidade de cálculo da CPU.
A biblioteca threading
A lib traz alguns pontos importantes:
Porque o sistema operacional está no controle de quando uma task será interrompida e outra task irá começar, qualquer dado que for compartilhado entre as threads precisa ser protegido, ou thread-safe. Infelizmente
requests.Session()não é thread-safe. Existem várias estratégias para fazer o acesso de dados thread-safe a depender de que dado é e como você está usando. Uma delas é usar estruturas de dados thread-safe comoQueuedo móduloqueuedo Python.
Encontramos a documentação do na documentação do Python:
multiprocessingé um pacote que suporta gerar processos usando uma API similar ao módulothreading. O pacotemultiprocessingoferece concorrência tanto local quanto remota, efetivamente desviando o GIL usando sub-processos ao invés de threads. Por isso o módulomultiprocessingpermite o programador aproveitar múltiplos processadores em uma máquina.
Vale apontar que rodar mais de um processo em diferentes cores de CPU não significa desabilitar o GIL, e sim que cada processo terá o seu próprio GIL. Por aproveitar de mais de um core de CPU, compartilhando workloads pesados de CPU entre os múltiplos cores dispiníveis, a lib é mais adequada a CPU bound.
Fontes:
FOWLER, Matthew. . Rio de Janeiro: LTC, 2013.
SOCIAL SHARE CARD GENERATOR