En Python, la biblioteca estándar proporciona el módulo threading para la multihilo. Los hilos permiten realizar varias operaciones en paralelo dentro de un mismo proceso. Sin embargo, en la implementación estándar de Python (CPython) existe un mecanismo llamado GIL (Global Interpreter Lock) — un bloqueo global del intérprete que permite que solo un hilo ejecute el bytecode de Python a la vez.
Esto significa que en CPython, la multihilo no permite lograr un verdadero paralelismo al ejecutar código de Python en el nivel del procesador; la paralelismo es útil solo para tareas relacionadas con la espera (I/O-bound). Para tareas CPU-bound, se recomienda utilizar el módulo multiprocessing, que inicia varios procesos y evita el GIL.
Ejemplo:
import threading def worker(): print('Start') # cálculos pesados print('End') threads = [threading.Thread(target=worker) for _ in range(5)] for t in threads: t.start() for t in threads: t.join()
Para el paralelismo en cálculos intensivos, use multiprocessing:
from multiprocessing import Pool def square(x): return x*x with Pool(4) as p: print(p.map(square, [1, 2, 3, 4]))
¿Puede la multihilo en Python acelerar la ejecución de tareas computacionales pesadas?
Respuesta: No, debido al GIL en la implementación estándar de Python (CPython), los hilos no ofrecen una mejora en el rendimiento en tareas CPU-bound; para tales tareas, utilice multiprocessing o implementaciones alternativas del intérprete (por ejemplo, Jython, IronPython), que no tienen GIL.
Historia
En un proyecto de procesamiento de grandes volúmenes de datos, el equipo intentó acelerar los cálculos usando hilos (
threading). En lugar de acelerar, el tiempo de ejecución aumentó, porque el GIL no permitía que los hilos trabajaran en paralelo; tras cambiar amultiprocessing, la tarea se resolvió.
Historia
Un desarrollador intentó descargar grandes archivos y procesarlos en varios hilos simultáneamente, pero a menudo se encontraba con un "deadlock" debido al uso imprudente de variables compartidas sin bloqueos (seguridad de hilos).
Historia
En un servidor backend, se implementó el procesamiento de solicitudes pesadas en un grupo de hilos. A medida que aumentaba la carga, el servidor comenzó a "congelarse"; se descubrió que la mayor parte del tiempo, los hilos estaban esperando la ejecución del código de Python debido al GIL, aunque las solicitudes no estaban relacionadas con I/O intensivo.