15.12.2022 Views

Python Eficaz

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Item 38: Use Lock para evitar que as threads iniciem

condições de corrida nos dados

Depois de aprender sobre a global interpreter lock (GIL) (consulte o Item 37:

“Use threads para bloquear I/O e evitar paralelismo”), muitos programadores

novatos em Python inferem que podem deixar de usar as travas de exclusão

mútua (mutual-exclusion locks, ou mutexes) no código. Se a GIL já está

impedindo que as threads do Python sejam executadas paralelamente em mais de

um núcleo de CPU, também deve atuar como trava para as estruturas de dados

do programa, certo? Se fizermos alguns testes em tipos como listas e dicionários,

poderíamos até supor que essa premissa seja verdadeira.

Cuidado! Essa inferência é completamente falsa! A GIL não protegerá seus

dados. Embora apenas uma thread de Python esteja sendo executada em um

dado momento, a operação de uma thread em estruturas de dados pode ser

interrompida a qualquer tempo entre duas instruções bytecode no interpretador

Python. Isso é perigoso quando mais de uma thread acessa simultaneamente o

mesmo objeto. Essas interrupções podem, a qualquer momento, violar as

invariantes de suas estruturas de dados, deixando seu programa em um estado de

total corrupção.

Por exemplo, digamos que se queira escrever um programa que conte muitas

coisas em paralelo, como, por exemplo, amostrar os níveis de luz em uma rede

de sensores fotossensíveis. Se for necessário determinar o número total de

amostras em função do tempo, podemos agregá-los em uma nova classe.

class Counter(object):

def __init__(self):

self.count = 0

def increment(self, offset):

self.count += offset

Imagine que cada sensor tem sua própria thread de trabalho porque a ação de

leitura no sensor bloqueia I/O. Depois de cada medição, a thread de trabalho

incrementa um contador até um limite máximo de leituras desejadas.

def worker(sensor_index, how_many, counter):

for _ in range(how_many):

www.full-ebook.com

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!