IT story

Python의 "스레드 로컬 저장소"란 무엇이며 왜 필요합니까?

hot-time 2020. 9. 9. 20:13
반응형

Python의 "스레드 로컬 저장소"란 무엇이며 왜 필요합니까?


특히 파이썬에서 변수는 스레드간에 어떻게 공유됩니까?

threading.Thread전에 사용했지만 변수가 공유되는 방법에 대한 예를 실제로 이해하거나 본 적이 없습니다. 메인 스레드와 자식간에 공유됩니까, 아니면 자식간에 만 공유됩니까? 이 공유를 피하기 위해 언제 스레드 로컬 스토리지를 사용해야합니까?

잠금을 사용하여 스레드간에 공유 데이터에 대한 액세스를 동기화하는 것에 대한 많은 경고를 보았지만 아직 문제에 대한 좋은 예를 보지 못했습니다.

미리 감사드립니다!


파이썬에서는 함수 지역 변수를 제외한 모든 것이 공유됩니다 (각 함수 호출이 자체 지역 집합을 가져오고 스레드는 항상 별도의 함수 호출이기 때문입니다.) 그리고 심지어 변수 자체 (객체를 참조하는 이름) 만 함수에 국한됩니다. 객체 자체는 항상 전역 적이며 어떤 것이 든이를 참조 할 수 있습니다. Thread특정 스레드에 대한 객체는이 점에서 특별한 개체가 아닙니다. Thread전역 변수와 같이 모든 스레드가 액세스 할 수있는 위치 객체 를 저장하면 모든 스레드가 해당 Thread객체에 액세스 할 수 있습니다 . 당신은 원자 수정하려면 아무것도이 동일한 스레드에서 생성 한 것이 아니라 다른 스레드가 접근 할 수있는 곳에 저장하지 않은 경우 잠금으로 보호해야합니다. 그리고 모든 스레드는 물론이 동일한 잠금을 공유해야합니다. 그렇지 않으면 그다지 효과적이지 않습니다.

실제 쓰레드-로컬 스토리지를 원한다면, 그것이 threading.local온다. 속성은 threading.local쓰레드간에 공유되지 않는다. 각 스레드는 자신이 배치 한 속성 만 봅니다. 구현에 대해 궁금한 경우 소스는 표준 라이브러리의 _threading_local.py 에 있습니다.


다음 코드를 고려하십시오.

#/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 ()
Thread-2에서 전화를 받았습니다.
나는 Thread-1에서 호출되었습니다. 

여기서 threading.local ()은 foo ()의 인터페이스를 변경하지 않고 run ()에서 bar ()로 일부 데이터를 전달하는 빠르고 더러운 방법으로 사용됩니다.

전역 변수를 사용하는 것은 트릭을 수행하지 않습니다.

#/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 ()
Thread-2에서 전화를 받았습니다.
Thread-2에서 전화를 받았습니다. 

한편,이 데이터를 foo ()의 인수로 전달할 여유가 있다면 더 우아하고 잘 설계된 방법이 될 것입니다.

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

그러나 타사 또는 잘못 설계된 코드를 사용할 때 항상 가능한 것은 아닙니다.


을 사용하여 스레드 로컬 저장소를 만들 수 있습니다 threading.local().

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

TLS에 저장된 데이터는 각 스레드에 고유하므로 의도하지 않은 공유가 발생하지 않도록합니다.


다른 모든 언어와 마찬가지로 Python의 모든 스레드는 동일한 변수에 액세스 할 수 있습니다. '메인 스레드'와 자식 스레드 사이에는 구분이 없습니다.

One difference with Python is that the Global Interpreter Lock means that only one thread can be running Python code at a time. This isn't much help when it comes to synchronising access, however, as all the usual pre-emption issues still apply, and you have to use threading primitives just like in other languages. It does mean you need to reconsider if you were using threads for performance, however.

참고URL : https://stackoverflow.com/questions/104983/what-is-thread-local-storage-in-python-and-why-do-i-need-it

반응형