Contenidos
El multithreading en Python permite la ejecución concurrente de tareas dentro de un único proceso. Esto es útil para operaciones que pueden realizarse en paralelo, como la E/S de archivos o la descarga de datos, pero no siempre mejora el rendimiento en tareas pesadas debido al GIL (Global Interpreter Lock) en CPython.
1. Creación de hilos con la clase Thread
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import threading def tarea(): print("Tarea en ejecución") # Crear un hilo hilo = threading.Thread(target=tarea) # Iniciar el hilo hilo.start() # Esperar a que el hilo termine hilo.join() |
En este ejemplo, se crea un hilo que ejecuta la función tarea()
. El método start()
inicia el hilo y join()
espera a que termine.
2. Creación de hilos utilizando clases
1 2 3 4 5 6 7 8 9 10 |
import threading class MiHilo(threading.Thread): def run(self): print("Tarea del hilo en ejecución") # Crear e iniciar el hilo hilo = MiHilo() hilo.start() hilo.join() |
Aquí, se define una clase MiHilo
que hereda de threading.Thread
y sobreescribe el método run()
con la tarea a ejecutar en el hilo.
3. Ejecución de múltiples hilos
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import threading def tarea(num): print(f"Hilo {num} en ejecución") # Crear e iniciar varios hilos hilos = [] for i in range(5): hilo = threading.Thread(target=tarea, args=(i,)) hilos.append(hilo) hilo.start() # Esperar a que todos los hilos terminen for hilo in hilos: hilo.join() |
Este código inicia múltiples hilos, cada uno ejecutando la función tarea()
con un número de identificación diferente.
4. Bloqueo de hilos (threading.Lock)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import threading contador = 0 bloqueo = threading.Lock() def incrementar(): global contador with bloqueo: local_contador = contador local_contador += 1 contador = local_contador # Crear e iniciar varios hilos hilos = [] for _ in range(10): hilo = threading.Thread(target=incrementar) hilos.append(hilo) hilo.start() # Esperar a que todos los hilos terminen for hilo in hilos: hilo.join() print(f"Valor final del contador: {contador}") |
El uso de threading.Lock
garantiza que solo un hilo acceda a una sección crítica del código a la vez, evitando condiciones de carrera.
5. Uso de threading.RLock
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import threading bloqueo = threading.RLock() def tarea1(): with bloqueo: print("Tarea 1 adquirió el bloqueo") tarea2() def tarea2(): with bloqueo: print("Tarea 2 adquirió el bloqueo") # Crear e iniciar el hilo hilo = threading.Thread(target=tarea1) hilo.start() hilo.join() |
threading.RLock
permite que un hilo adquiera un bloqueo que ya posee, lo cual es útil para evitar interbloqueos.
El multithreading es ideal para aplicaciones de E/S intensiva. Para CPU-bound tasks, se recomienda usar multiprocessing
para aprovechar múltiples núcleos.