pthread_create hilos ejemplo dev python multithreading language-agnostic

ejemplo - Hilos de Python-Sección crítica



hilos en dev c++ (3)

Otras personas han dado muy buenas definiciones. Este es el ejemplo clásico:

import threading account_balance = 0 # The "resource" that zenazn mentions. account_balance_lock = threading.Lock() def change_account_balance(delta): global account_balance with account_balance_lock: # Critical section is within this block. account_balance += delta

Digamos que el operador += consta de tres subcomponentes:

  • Lee el valor actual
  • Agregue el RHS a ese valor
  • Escriba el valor acumulado en el LHS (técnicamente agréguelo en términos de Python)

Si no tiene la with account_balance_lock y ejecuta dos llamadas a change_account_balance en paralelo, puede terminar intercalando las tres operaciones de subcomponentes de manera peligrosa. Supongamos que llama simultáneamente change_account_balance(100) (AKA pos) y change_account_balance(-100) (AKA neg). Esto podría suceder:

pos = threading.Thread(target=change_account_balance, args=[100]) neg = threading.Thread(target=change_account_balance, args=[-100]) pos.start(), neg.start()

  • pos: leer el valor actual -> 0
  • neg: leer el valor actual -> 0
  • pos: agrega el valor actual para leer el valor -> 100
  • neg: agrega el valor actual para leer el valor -> -100
  • pos: escribe el valor actual -> account_balance = 100
  • neg: escribir el valor actual -> account_balance = -100

Debido a que no obligó a las operaciones a suceder en trozos discretos, puede tener tres resultados posibles (-100, 0, 100).

La sentencia with [lock] es una operación única e indivisible que dice: "Permítanme ser el único hilo que ejecuta este bloque de código. Si algo más se está ejecutando, está bien, esperaré". Esto garantiza que las actualizaciones de account_balance sean "thread-safe" (paralelismo-safe).

Nota: Este esquema tiene una salvedad: debe recordar adquirir el account_balance_lock (via with ) cada vez que desee manipular el account_balance para que el código permanezca seguro para subprocesos. Hay formas de hacer esto menos frágil, pero esa es la respuesta a otra pregunta.

Editar: En retrospectiva, es probable que sea importante mencionar que la declaración with llama implícitamente una acquire bloqueo en el bloqueo: esta es la parte "Voy a esperar" del diálogo de subproceso anterior. Por el contrario, una adquisición sin bloqueo dice: "Si no puedo adquirir la cerradura de inmediato, hágamelo saber", y luego confía en usted para verificar si tiene la cerradura o no.

import logging # This module is thread safe. import threading LOCK = threading.Lock() def run(): if LOCK.acquire(False): # Non-blocking -- return whether we got it logging.info(''Got the lock!'') LOCK.release() else: logging.info("Couldn''t get the lock. Maybe next time") logging.basicConfig(level=logging.INFO) threads = [threading.Thread(target=run) for i in range(100)] for thread in threads: thread.start()

También quiero agregar que el objetivo principal de la cerradura es garantizar la atomicidad de la adquisición (la indivisibilidad de la acquire través de los hilos), que un indicador booleano simple no garantizará. La semántica de las operaciones atómicas probablemente también sea el contenido de otra pregunta.

¿Cuál es la "sección crítica" de un hilo (en Python)?

Un hilo entra en la sección crítica llamando al método acquire (), que puede ser de bloqueo o no bloqueo. Un hilo sale de la sección crítica, llamando al método release ().

- Comprensión de Threading en Python, Linux Gazette

Además, ¿cuál es el propósito de un bloqueo?


Una "sección crítica" es un fragmento de código en el cual, para ser correcto, es necesario asegurar que solo un hilo de control pueda estar en esa sección a la vez. En general, necesita una sección crítica para contener referencias que escriben valores en la memoria que se pueden compartir entre más de un proceso simultáneo.


Una sección crítica de código es aquella que solo puede ejecutarse por un hilo a la vez. Tome un servidor de chat, por ejemplo. Si tiene un hilo para cada conexión (es decir, cada usuario final), una "sección crítica" es el código de spooling (enviando un mensaje entrante a todos los clientes). Si más de un hilo intenta entablar un mensaje al mismo tiempo, obtendrá BFRIToS mANtwD PIoEmesCEsaSges entrelazados, lo que obviamente no es bueno en absoluto.

Un bloqueo es algo que se puede usar para sincronizar el acceso a una sección crítica (o recursos en general). En nuestro ejemplo de servidor de chat, el bloqueo es como una habitación cerrada con una máquina de escribir. Si hay un hilo allí (para escribir un mensaje), no puede entrar ningún otro hilo en la sala. Una vez que el primer hilo está listo, él abre la habitación y se va. Luego, otro hilo puede ir a la habitación (bloquearlo). "Aquiring" la cerradura solo significa "Consigo la habitación".