Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

223
Vistas
¿Por qué este código de Python con subprocesos tiene condiciones de carrera?

Este código crea una condición de carrera:

 import threading ITERS = 100000 x = [0] def worker(): for _ in range(ITERS): x[0] += 1 # this line creates a race condition # because it takes a value, increments and then writes # some inrcements can be done together, and lost def main(): x[0] = 0 # you may use `global x` instead of this list trick too t1 = threading.Thread(target=worker) t2 = threading.Thread(target=worker) t1.start() t2.start() t1.join() t2.join() for i in range(5): main() print(f'iteration {i}. expected x = {ITERS*2}, got {x[0]}')

Producción:

 $ python3 test.py iteration 0. expected x = 200000, got 200000 iteration 1. expected x = 200000, got 148115 iteration 2. expected x = 200000, got 155071 iteration 3. expected x = 200000, got 200000 iteration 4. expected x = 200000, got 200000

Versión Python3:

 Python 3.9.7 (default, Sep 10 2021, 14:59:43) [GCC 11.2.0] on linux

Pensé que GIL lo evitaría y no permitiría que dos subprocesos se ejecutaran juntos hasta que hicieran algo relacionado con io o llamaran a una biblioteca C. Al menos esto es lo que puede concluir de los documentos .

Entonces, ¿qué hace realmente GIL y cuándo se ejecutan los subprocesos en paralelo?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Leyendo mejor los documentos , creo que ahí está la respuesta:

El mecanismo utilizado por el intérprete de CPython para garantizar que solo un subproceso ejecute el código de bytes de Python a la vez . Esto simplifica la implementación de CPython al hacer que el modelo de objetos (incluidos los tipos integrados críticos como dict) sea implícitamente seguro contra el acceso simultáneo. Bloquear todo el intérprete facilita que el intérprete sea multiproceso, a expensas de gran parte del paralelismo que ofrecen las máquinas multiprocesador.

Sin embargo, algunos módulos de extensión, ya sean estándar o de terceros, están diseñados para liberar la GIL cuando se realizan tareas de computación intensiva, como compresión o hash. Además, el GIL siempre se libera al realizar E/S.

No conozco los aspectos internos, pero supongo que cada línea o bloque de este código de bytes se ejecuta solo, y otros subprocesos están esperando (lo que lo hace lento). Pero algunas líneas constan de varios bloques y no son atómicas.

Esto es lo que obtienes si ejecutas dis.dis('x[0] += 1') :

 0 LOAD_NAME 0 (x) 2 LOAD_CONST 0 (0) 4 DUP_TOP_TWO 6 BINARY_SUBSCR 8 LOAD_CONST 1 (1) 10 INPLACE_ADD 12 ROT_THREE 14 STORE_SUBSCR 16 LOAD_CONST 2 (None) 18 RETURN_VALUE

Algunos de estos se ejecutan de manera concurrente y hacen la condición de carrera. Entonces, GIL solo garantiza que las partes internas de estructuras como list o dict no se dañarán.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda