La concurrencia es una técnica que permite que múltiples tareas se ejecuten de manera simultánea, mejorando la eficiencia y el rendimiento de las aplicaciones. En Python, la concurrencia se puede lograr utilizando hilos (threads) y procesos (processes). Este tema cubre los conceptos básicos de hilos y procesos, cómo utilizarlos en Python, y proporciona ejemplos prácticos y ejercicios para reforzar el aprendizaje.

Conceptos Clave

  1. Concurrencia vs. Paralelismo:

    • Concurrencia: Múltiples tareas progresan simultáneamente.
    • Paralelismo: Múltiples tareas se ejecutan exactamente al mismo tiempo, generalmente en múltiples núcleos de CPU.
  2. Hilos (Threads):

    • Un hilo es la unidad más pequeña de procesamiento que puede ser programada.
    • Los hilos comparten el mismo espacio de memoria dentro de un proceso.
  3. Procesos (Processes):

    • Un proceso es una instancia de un programa en ejecución.
    • Los procesos tienen su propio espacio de memoria independiente.

Hilos en Python

Python proporciona el módulo threading para trabajar con hilos. A continuación, se muestra un ejemplo básico de cómo crear y ejecutar hilos.

Ejemplo: Uso de Hilos

import threading
import time

def print_numbers():
    for i in range(5):
        print(f"Number: {i}")
        time.sleep(1)

def print_letters():
    for letter in 'abcde':
        print(f"Letter: {letter}")
        time.sleep(1)

# Crear hilos
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)

# Iniciar hilos
thread1.start()
thread2.start()

# Esperar a que los hilos terminen
thread1.join()
thread2.join()

print("Hilos completados")

Explicación del Código

  1. Importación de Módulos: Se importan los módulos threading y time.
  2. Definición de Funciones: Se definen dos funciones, print_numbers y print_letters, que imprimen números y letras respectivamente.
  3. Creación de Hilos: Se crean dos hilos, thread1 y thread2, asignando las funciones como objetivos.
  4. Inicio de Hilos: Se inician los hilos con start().
  5. Esperar Finalización: Se utiliza join() para esperar a que ambos hilos terminen antes de continuar.

Procesos en Python

Para trabajar con procesos, Python proporciona el módulo multiprocessing. A continuación, se muestra un ejemplo básico de cómo crear y ejecutar procesos.

Ejemplo: Uso de Procesos

import multiprocessing
import time

def print_numbers():
    for i in range(5):
        print(f"Number: {i}")
        time.sleep(1)

def print_letters():
    for letter in 'abcde':
        print(f"Letter: {letter}")
        time.sleep(1)

# Crear procesos
process1 = multiprocessing.Process(target=print_numbers)
process2 = multiprocessing.Process(target=print_letters)

# Iniciar procesos
process1.start()
process2.start()

# Esperar a que los procesos terminen
process1.join()
process2.join()

print("Procesos completados")

Explicación del Código

  1. Importación de Módulos: Se importan los módulos multiprocessing y time.
  2. Definición de Funciones: Se definen dos funciones, print_numbers y print_letters, que imprimen números y letras respectivamente.
  3. Creación de Procesos: Se crean dos procesos, process1 y process2, asignando las funciones como objetivos.
  4. Inicio de Procesos: Se inician los procesos con start().
  5. Esperar Finalización: Se utiliza join() para esperar a que ambos procesos terminen antes de continuar.

Comparación: Hilos vs. Procesos

Característica Hilos (Threads) Procesos (Processes)
Espacio de Memoria Comparten el mismo espacio de memoria Tienen su propio espacio de memoria
Creación Más rápidos y ligeros Más lentos y pesados
Comunicación Más fácil (comparten memoria) Más difícil (necesitan mecanismos de IPC)
Seguridad Menos seguros (problemas de sincronización) Más seguros (memoria independiente)

Ejercicio Práctico

Ejercicio 1: Contador Concurrente

Escribe un programa que cree dos hilos. Un hilo debe contar de 1 a 5 y el otro hilo debe contar de 6 a 10. Ambos hilos deben imprimir los números con un retraso de 1 segundo entre cada número.

Solución

import threading
import time

def count_up_to_5():
    for i in range(1, 6):
        print(f"Count 1-5: {i}")
        time.sleep(1)

def count_up_to_10():
    for i in range(6, 11):
        print(f"Count 6-10: {i}")
        time.sleep(1)

# Crear hilos
thread1 = threading.Thread(target=count_up_to_5)
thread2 = threading.Thread(target=count_up_to_10)

# Iniciar hilos
thread1.start()
thread2.start()

# Esperar a que los hilos terminen
thread1.join()
thread2.join()

print("Contadores completados")

Ejercicio 2: Procesos Concurrentes

Escribe un programa que cree dos procesos. Un proceso debe imprimir "Proceso 1" cinco veces con un retraso de 1 segundo entre cada impresión, y el otro proceso debe imprimir "Proceso 2" cinco veces con el mismo retraso.

Solución

import multiprocessing
import time

def process_one():
    for _ in range(5):
        print("Proceso 1")
        time.sleep(1)

def process_two():
    for _ in range(5):
        print("Proceso 2")
        time.sleep(1)

# Crear procesos
process1 = multiprocessing.Process(target=process_one)
process2 = multiprocessing.Process(target=process_two)

# Iniciar procesos
process1.start()
process2.start()

# Esperar a que los procesos terminen
process1.join()
process2.join()

print("Procesos completados")

Resumen

En esta sección, hemos cubierto los conceptos básicos de concurrencia utilizando hilos y procesos en Python. Aprendimos cómo crear y manejar hilos y procesos, y discutimos las diferencias clave entre ellos. Además, proporcionamos ejemplos prácticos y ejercicios para reforzar el aprendizaje. La concurrencia es una herramienta poderosa para mejorar el rendimiento de las aplicaciones, y comprender cómo utilizar hilos y procesos es esencial para cualquier programador avanzado en Python.

En el próximo tema, exploraremos los Administradores de Contexto, una característica avanzada de Python que facilita la gestión de recursos como archivos y conexiones de red.

Curso de Programación en Python

Módulo 1: Introducción a Python

Módulo 2: Estructuras de Control

Módulo 3: Funciones y Módulos

Módulo 4: Estructuras de Datos

Módulo 5: Programación Orientada a Objetos

Módulo 6: Manejo de Archivos

Módulo 7: Manejo de Errores y Excepciones

Módulo 8: Temas Avanzados

Módulo 9: Pruebas y Depuración

Módulo 10: Desarrollo Web con Python

Módulo 11: Ciencia de Datos con Python

Módulo 12: Proyecto Final

© Copyright 2024. Todos los derechos reservados