Solución:
La asignación simple a variables simples es “atómica” AKA segura para subprocesos (asignaciones compuestas como +=
o las asignaciones a elementos o atributos de objetos no necesitan serlo, pero su ejemplo es una asignación simple a una variable simple, aunque global, por lo tanto segura).
La Guía de estilo de Google lo desaconseja
No estoy afirmando que las guías de estilo de Google sean la verdad absoluta, pero el fundamento de la sección “Subprocesos” da una idea (lo más destacado es mío):
No confíe en la atomicidad de los tipos integrados.
Si bien los tipos de datos integrados de Python, como los diccionarios, parecen tener operaciones atómicas, hay casos extremos en los que no son atómicos (por ejemplo, si
__hash__
o__eq__
se implementan como métodos de Python) y no se debe confiar en su atomicidad. Tampoco debe confiar en la asignación de variables atómicas (ya que esto a su vez depende de los diccionarios).Utilizar el
Queue
tipo de datos de cola del módulo como la forma preferida de comunicar datos entre subprocesos. De lo contrario, utilice el módulo de subprocesamiento y sus primitivas de bloqueo. Obtenga información sobre el uso adecuado de las variables de condición para que pueda utilizarthreading.Condition
en lugar de utilizar cerraduras de nivel inferior.
Entonces mi interpretación es que en Python todo es como un dictado y cuando lo haces a = b
en el backend en algún lugar globals['a'] = b
está sucediendo, lo cual es malo ya que los dictados no son necesariamente seguros para subprocesos.
Para una sola variable, Queue
Sin embargo, no es ideal, ya que queremos que contenga solo un elemento, y no pude encontrar un contenedor preexistente perfecto en stdlib que sincronice automáticamente un .set()
método. Así que por ahora solo estoy haciendo:
import threading
myvar = 0
myvar_lock = threading.Lock()
with myvar_lock:
myvar = 1
with myvar_lock:
myvar = 2
Es interesante que a Martelli no parece importarle la recomendación de la guía de estilo de Google 🙂 (trabaja en Google)
Me pregunto si CPython GIL tiene implicaciones para esta pregunta: ¿Qué es el bloqueo de intérprete global (GIL) en CPython?
Este hilo también sugiere que los dictados de CPython son seguros para subprocesos, incluida la siguiente cita del glosario que lo menciona explícitamente https://docs.python.org/3/glossary.html#term-global-interpreter-lock
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 concurrente.