Python에서 "스레드 로컬 스토리지"란 무엇이며, 왜 필요합니까?
구체적으로 파이썬에서 변수는 스레드 간에 어떻게 공유됩니까?
나는 을 해 보았지만요.threading.Thread
변수들이 어떻게 공유되는지에 대한 예를 전혀 이해하지 못했거나 보지도 못했습니다.그것들은 메인 실과 아이들 사이에 공유되니 아니면 아이들 사이에서만 공유되니?이 공유를 피하기 위해 스레드 로컬 스토리지를 언제 사용해야 합니까?
잠금을 사용하여 스레드 간에 공유 데이터에 대한 액세스를 동기화하는 것에 대한 경고는 많이 보았지만 문제의 좋은 예는 아직 보지 못했습니다.
Python에서는 함수-로컬 변수를 제외하고 모든 것이 공유됩니다(각 함수 호출은 고유한 로컬 집합을 가지며 스레드는 항상 별개의 함수 호출이기 때문입니다).그리고 그 때에도 변수 자체(객체를 지칭하는 이름)만이 함수에 국소적입니다; 객체 자체는 항상 전역적이고, 무엇이든 그들을 지칭할 수 있습니다.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과 다른 점은 Global Interpreter Lock은 한 번에 하나의 스레드만 Python 코드를 실행할 수 있다는 것을 의미합니다.그러나 일반적인 선취 문제가 여전히 적용되고, 다른 언어와 마찬가지로 스레드화된 프리미티브를 사용해야 하기 때문에 액세스 동기화에 있어서는 큰 도움이 되지 않습니다.그러나 성능을 위해 스레드를 사용하고 있었는지 재고해야 합니다.
제가 틀렸을 수도 있습니다.다른 방법을 알고 있는 경우에는 스레드 로컬()을 사용해야 하는 이유를 설명하는 데 도움이 됩니다.
"다른 스레드가 액세스할 수 있는 모든 것을 원자적으로 수정하려면 잠금 장치를 사용하여 보호해야 합니다."라는 이 문장은 틀린 것이 아닌 것 같습니다.나는 이 진술이 효과적으로 ->맞다고 생각하지만 완전히 정확하지는 않습니다.저는 파이썬 인터프리터가 CPU에 인터럽트 신호를 보낼 공간을 남기지 않는 바이트 코드 청크를 생성했다는 것을 의미한다고 생각했습니다.
저는 원자 연산이 인터럽트에 접근할 수 없는 파이썬 바이트 코드의 덩어리라고 생각했습니다."running = True"와 같은 Python 문장은 원자입니다.이 경우에는 CPU를 인터럽트로부터 잠글 필요가 없습니다(생각합니다).Python 바이트 코드 분해는 스레드 중단으로부터 안전합니다.
"threads_running[5] = True"와 같은 파이썬 코드는 원자 코드가 아닙니다.여기에는 두 개의 파이썬 바이트 코드 청크가 있습니다. 하나는 개체에 대한 목록()의 참조를 취소하는 것이고 다른 하나는 개체에 값을 할당하는 것입니다. 이 경우 목록의 "place"입니다.두 바이트 코드 -> 청크 <-> 사이에 인터럽트가 발생할 수 있습니다.그건 나쁜 일이 일어났다는 겁니다.
스레드 로컬()이 "원자"와 어떤 관계가 있습니까?이것이 그 진술이 나에게 잘못 전달된 것처럼 보이는 이유입니다.그렇지 않다면 설명해 줄 수 있습니까?
를 할 가치가 .threading.local()
1톤이 아닙니다.
스레드당 더 많이 사용할 수 있습니다.하나의 저장소가 아닙니다.
언급URL : https://stackoverflow.com/questions/104983/what-is-thread-local-storage-in-python-and-why-do-i-need-it
'programing' 카테고리의 다른 글
첫 번째 발생만 찾는 XPath 식은 무엇입니까? (0) | 2023.10.09 |
---|---|
.bss vs COMMEN: 어디로 가는 거지? (0) | 2023.10.09 |
밑줄과 jshint 사용 (0) | 2023.10.09 |
Spring Boot에서 Tomcat JNDI JDBC 데이터 소스를 사용하는 방법 (0) | 2023.10.09 |
Vim으로 Git commit 메시지 입력 문제 (0) | 2023.10.09 |