Pregunta

Específicamente en Python, ¿cómo se comparten las variables entre subprocesos?

Aunque he usado threading.Thread Antes nunca entendí ni vi ejemplos de cómo se compartían las variables.¿Se comparten entre el hilo principal y los niños o solo entre los niños?¿Cuándo necesitaría utilizar el almacenamiento local de subprocesos para evitar este intercambio?

He visto muchas advertencias sobre la sincronización del acceso a datos compartidos entre subprocesos mediante el uso de bloqueos, pero todavía tengo que ver un ejemplo realmente bueno del problema.

¡Gracias de antemano!

¿Fue útil?

Solución

En Python, todo se comparte, excepto las variables locales de función (porque cada llamada de función tiene su propio conjunto de locales y los subprocesos son siempre llamadas de función separadas). E incluso entonces, solo las variables mismas (los nombres que se refieren a los objetos) son locales a la función;Los objetos en sí son siempre globales y cualquier cosa puede referirse a ellos.El Thread El objeto para un hilo en particular no es un objeto especial a este respecto.Si guardas el Thread objeto en algún lugar al que todos los subprocesos puedan acceder (como una variable global), entonces todos los subprocesos pueden acceder a ese Thread objeto.Si quieres modificar atómicamente cualquier cosa que no acaba de crear en este mismo hilo y no lo almacenó en ningún otro lugar al que otro hilo pueda acceder, debe protegerlo con un candado.Y, por supuesto, todos los hilos deben compartir este mismo candado, o no sería muy efectivo.

Si desea almacenamiento local de subprocesos real, ahí es donde threading.local viene en.Atributos de threading.local no se comparten entre hilos;cada hilo ve sólo los atributos que él mismo colocó allí.Si tiene curiosidad acerca de su implementación, la fuente está en _threading_local.py en la biblioteca estándar.

Otros consejos

Considere el siguiente código:

#/usr/bin/env python

from time import sleep
from random import random
from threading import Thread, local

data = local()

def bar():
    print("I'm called from", data.v)

def foo():
    bar()

class T(Thread):
    def run(self):
        sleep(random())
        data.v = self.getName()   # Thread-1 and Thread-2 accordingly
        sleep(1)
        foo()
 >> T().start(); T().start()
I'm called from Thread-2
I'm called from Thread-1 

Aquí threading.local() se utiliza como una forma rápida y sucia de pasar algunos datos de run() a bar() sin cambiar la interfaz de foo().

Tenga en cuenta que usar variables globales no funcionará:

#/usr/bin/env python

from time import sleep
from random import random
from threading import Thread

def bar():
    global v
    print("I'm called from", v)

def foo():
    bar()

class T(Thread):
    def run(self):
        global v
        sleep(random())
        v = self.getName()   # Thread-1 and Thread-2 accordingly
        sleep(1)
        foo()
 >> T().start(); T().start()
I'm called from Thread-2
I'm called from Thread-2 

Mientras tanto, si pudiera permitirse el lujo de pasar estos datos como argumento de foo(), sería una forma más elegante y mejor diseñada:

from threading import Thread

def bar(v):
    print("I'm called from", v)

def foo(v):
    bar(v)

class T(Thread):
    def run(self):
        foo(self.getName())

Pero esto no siempre es posible cuando se utiliza código de terceros o mal diseñado.

Puede crear almacenamiento local de subprocesos utilizando threading.local().

>>> tls = threading.local()
>>> tls.x = 4 
>>> tls.x
4

Los datos almacenados en el tls serán únicos para cada hilo, lo que ayudará a garantizar que no se compartan involuntariamente.

Al igual que en cualquier otro lenguaje, cada hilo en Python tiene acceso a las mismas variables.No hay distinción entre el 'hilo principal' y los subprocesos secundarios.

Una diferencia con Python es que el bloqueo global de intérprete significa que solo un subproceso puede ejecutar código Python a la vez.Sin embargo, esto no es de mucha ayuda cuando se trata de sincronizar el acceso, ya que todos los problemas habituales de preferencia aún se aplican y hay que usar primitivas de subprocesamiento como en otros lenguajes.Sin embargo, significa que debes reconsiderar si estabas usando subprocesos para mejorar el rendimiento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top