Pergunta

Em Python especificamente, como variáveis ??são compartilhadas entre segmentos?

Apesar de eu ter usado threading.Thread antes de eu nunca entendi ou exemplos de serra de como as variáveis ??foi compartilhado. eles são compartilhados entre o segmento principal e as crianças ou apenas entre as crianças? Quando eu precisaria de armazenamento local de segmento uso para evitar esta partilha?

Eu tenho visto muitos avisos sobre a sincronização de acesso a dados compartilhados entre threads usando bloqueios, mas eu ainda tenho que ver um bom exemplo do problema.

Agradecemos antecipadamente!

Foi útil?

Solução

Em Python, tudo é compartilhado, exceto para as variáveis ??de função-local (porque cada chamada função obtém seu próprio conjunto de moradores, e as roscas são sempre chamadas de funções separadas.) E mesmo assim, apenas as próprias variáveis ??(os nomes que se referem a objetos) são locais para a função; objetos em si são sempre global, e tudo pode se referir a eles. O objeto Thread para um segmento específico não é um objeto especial a este respeito. Se você armazenar a algum lugar Thread objeto os tópicos pode acessar (como uma variável global), em seguida, os tópicos podem acessar que um objeto Thread. Se você deseja modificar atomicamente qualquer que você não apenas criar neste mesmo segmento, e não armazenar em qualquer lugar outro segmento pode chegar a ele, você tem que protegê-lo por um bloqueio. E os tópicos deve, naturalmente, partilhar esta mesma fechadura, ou não seria muito eficaz.

Se você quiser armazenamento real de segmento local, que é onde threading.local vem em Atributos de threading.local não são compartilhados entre threads.; cada thread vê apenas os atributos que se colocava lá dentro. Se você está curioso sobre a sua implementação, a fonte está em _threading_local.py na biblioteca padrão.

Outras dicas

Considere o seguinte 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 

Aqui threading.local () é usado como uma maneira rápida e suja para passar alguns dados de run () para barrar () sem alterar a interface de foo ().

Note que o uso de variáveis ??globais não vai fazer o truque:

#/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 

Entretanto, se você poderia ter recursos para passar esses dados através como um argumento de foo () - seria uma maneira mais elegante e bem desenhado:

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())

Mas isso nem sempre é possível quando se utiliza de terceiros ou código mal projetado.

Você pode criar armazenamento local de thread usando threading.local().

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

Os dados armazenados para os TLS será exclusivo para cada thread que irá ajudar a garantir que o compartilhamento não intencional não ocorre.

Assim como em todas as outras linguagens, cada segmento em Python tem acesso às mesmas variáveis. Não há nenhuma distinção entre o 'fio condutor' e tópicos criança.

Uma diferença com Python é que o Global Interpreter Lock significa que apenas um thread pode estar executando código Python de cada vez. Isso não ajuda muito quando se trata de sincronizar o acesso, no entanto, como todos os problemas habituais de preferência ainda se aplicam, e você tem que usar enfiar primitivos assim como em outros idiomas. Isso significa que você precisa reconsiderar se você estivesse usando tópicos de desempenho, no entanto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top