Contenidos
En este ejercicio, vamos a simular varios hilos que intentan escribir en un archivo de registro simultáneamente. Utilizaremos un bloqueo (lock) para asegurar que solo un hilo pueda escribir en el archivo a la vez, evitando condiciones de carrera.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import threading import time import random # Definimos el bloqueo global lock = threading.Lock() def escribir_en_registro(hilo_id): with lock: with open("registro.log", "a") as archivo: tiempo = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) mensaje = f"{tiempo} - Hilo {hilo_id} escribiendo en el registro\n" archivo.write(mensaje) print(mensaje) time.sleep(random.uniform(0.1, 0.5)) def crear_hilos(num_hilos): hilos = [] for i in range(num_hilos): hilo = threading.Thread(target=escribir_en_registro, args=(i,)) hilos.append(hilo) hilo.start() for hilo in hilos: hilo.join() if __name__ == "__main__": crear_hilos(10) |
Explicación
1. Importaciones y definición del bloqueo global
1 2 3 4 5 |
import threading import time import random lock = threading.Lock() |
Importamos los módulos necesarios: threading
para manejar los hilos, time
para obtener la hora actual y random
para generar pausas aleatorias. Definimos un bloqueo global lock
que será usado para sincronizar el acceso al archivo de registro.
2. Función para escribir en el archivo de registro
1 2 3 4 5 6 7 8 |
def escribir_en_registro(hilo_id): with lock: with open("registro.log", "a") as archivo: tiempo = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) mensaje = f"{tiempo} - Hilo {hilo_id} escribiendo en el registro\n" archivo.write(mensaje) print(mensaje) time.sleep(random.uniform(0.1, 0.5)) |
La función escribir_en_registro
toma un identificador de hilo (hilo_id
) como argumento. Utiliza un bloqueo para asegurar que solo un hilo pueda escribir en el archivo a la vez. Dentro del bloqueo, abre el archivo registro.log
en modo de adición (a
), escribe un mensaje con la hora actual y el identificador del hilo, y luego cierra el archivo. También imprime el mensaje en la pantalla. Finalmente, el hilo duerme por un período aleatorio entre 0.1 y 0.5 segundos para simular trabajo.
3. Función para crear y gestionar los hilos
1 2 3 4 5 6 7 8 9 |
def crear_hilos(num_hilos): hilos = [] for i in range(num_hilos): hilo = threading.Thread(target=escribir_en_registro, args=(i,)) hilos.append(hilo) hilo.start() for hilo in hilos: hilo.join() |
La función crear_hilos
crea y gestiona un número de hilos especificado por num_hilos
. Para cada hilo, crea un objeto Thread
que ejecutará la función escribir_en_registro
con el identificador del hilo como argumento. Añade cada hilo a una lista y lo inicia. Luego, espera a que todos los hilos terminen utilizando join
.
4. Bloque principal
1 2 |
if __name__ == "__main__": crear_hilos(10) |
El bloque principal llama a la función crear_hilos
con 10 hilos. Esto inicia la simulación de acceso concurrente seguro al archivo de registro.

Explicación detallada
1 2 3 |
import threading import time import random |
Importaciones: Se importan tres módulos:
threading
: Para manejar la creación y gestión de hilos.time
: Para trabajar con el tiempo y las fechas.random
: Para generar números aleatorios, utilizado aquí para crear pausas aleatorias.
1 2 |
# Definimos el bloqueo global lock = threading.Lock() |
Definición del bloqueo global:
lock = threading.Lock()
: Crea un objeto de bloqueo (lock) que será utilizado para sincronizar el acceso al recurso compartido (archivo de registro) entre los hilos.
1 2 3 4 5 6 7 8 |
def escribir_en_registro(hilo_id): with lock: with open("registro.log", "a") as archivo: tiempo = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) mensaje = f"{tiempo} - Hilo {hilo_id} escribiendo en el registro\n" archivo.write(mensaje) print(mensaje) time.sleep(random.uniform(0.1, 0.5)) |
Función escribir_en_registro
:
def escribir_en_registro(hilo_id):
: Define una función que toma un identificador de hilo (hilo_id
) como argumento.with lock:
: Utiliza el bloqueo para asegurar que solo un hilo pueda ejecutar el bloque de código dentro delwith
a la vez.with open("registro.log", "a") as archivo:
: Abre el archivoregistro.log
en modo de adición ("a"
) para que las escrituras se añadan al final del archivo.tiempo = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()):
Obtiene la fecha y hora actual en un formato legible.mensaje = f"{tiempo} - Hilo {hilo_id} escribiendo en el registro\n":
Crea un mensaje que incluye la hora actual y el identificador del hilo.archivo.write(mensaje):
Escribe el mensaje en el archivo de registro.print(mensaje):
Imprime el mensaje en la salida estándar (pantalla).time.sleep(random.uniform(0.1, 0.5)):
Pausa el hilo por un período aleatorio entre 0.1 y 0.5 segundos para simular trabajo.
1 2 3 4 5 6 7 8 9 |
def crear_hilos(num_hilos): hilos = [] for i in range(num_hilos): hilo = threading.Thread(target=escribir_en_registro, args=(i,)) hilos.append(hilo) hilo.start() for hilo in hilos: hilo.join() |
Función crear_hilos
:
def crear_hilos(num_hilos):
: Define una función que toma el número de hilos a crear (num_hilos
) como argumento.hilos = []:
Inicializa una lista vacía para almacenar los hilos.for i in range(num_hilos):
Itera desde 0 hastanum_hilos-1
.hilo = threading.Thread(target=escribir_en_registro, args=(i,)):
Crea un nuevo hilo que ejecutará la funciónescribir_en_registro
con el identificador del hilo (i
) como argumento.hilos.append(hilo):
Añade el hilo creado a la lista de hilos.hilo.start():
Inicia la ejecución del hilo.for hilo in hilos:
Itera sobre la lista de hilos.hilo.join():
Espera a que cada hilo termine su ejecución antes de continuar.
1 2 |
if __name__ == "__main__": crear_hilos(10) |
Bloque principal:
if __name__ == "__main__":
Comprueba si el script se está ejecutando directamente (no importado como módulo).crear_hilos(10):
Llama a la funcióncrear_hilos
con 10 hilos, iniciando así la simulación de acceso concurrente seguro al archivo de registro.