es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué este código de Python con subprocesamiento tiene condiciones de carrera?

Este código crea una condición de carrera:

import threading

ITERS = 100000
x = [0]

def worker():
for _ in range(ITERS):
x[0] += 1 # esta línea crea una condición de carrera
# porque toma un valor, lo incrementa y luego lo escribe
# algunos incrementos pueden hacerse juntos y perderse

def main():
x[0] = 0 # también se puede usar global x en lugar de esto truco con lista
t1 = threading.Thread(target=worker)
t2 = threading.Thread(target=worker)
t1.start()
t2.start()
t1.join()
t2.join()

for i in range(5):
main()
print(f’iteración {i}. se esperaba que x = {ITERS*2}, se obtuvo {x[0]}’)

Salida:

$ python3 test.py
iteración 0. se esperaba que x = 200000, se obtuvo 200000
iteración 1. se esperaba que x = 200000, se obtuvo 148115
iteración 2. se esperaba que x = 200000, se obtuvo 155071
iteración 3. se esperaba que x = 200000, se obtuvo 200000
iteración 4. se esperaba que x = 200000, se obtuvo 200000

Versión de Python3:

Python 3.9.7 (por defecto, 10 de septiembre de 2021, 14:59:43)
[GCC 11.2.0] en linux

Pensé que el GIL lo evitaría y no permitiría que dos hilos se ejecutaran juntos hasta que hicieran algo relacionado con la entrada/salida o llamado a una biblioteca de C. Al menos esto es lo que se puede concluir de los documentos.

Entonces, ¿qué hace realmente el GIL y cuándo se ejecutan los hilos en paralelo?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El GIL (Global Interpreter Lock) en Python es un mecanismo utilizado para sincronizar el acceso al intérprete de Python, lo cual asegura que solo un hilo ejecute bytecode de Python a la vez. Esto significa que, aun en máquinas de múltiples núcleos, los hilos de Python no pueden ejecutarse en paralelo ya que están limitados por el GIL.

    Sin embargo, el GIL no evita que ocurran condiciones de carrera cuando múltiples hilos acceden y modifican datos compartidos, como la variable x en el ejemplo anterior. De hecho, el GIL puede incluso agravar las condiciones de carrera porque permite que los hilos se interrumpan entre sí en medio de secciones críticas, lo que resulta en un comportamiento inesperado.

    Para prevenir condiciones de carrera en Python, se pueden utilizar primitivas de sincronización como bloqueos, semáforos y variables de condición para coordinar el acceso a recursos compartidos entre hilos. Alternativamente, se puede usar multiprocesamiento en lugar de hilos, ya que crea procesos separados que no comparten memoria y, por lo tanto, evitan por completo las condiciones de carrera.

Comments are closed.