파이썬에서 스레드로부터 안전한 정렬 된 컬렉션 구현이 있습니까?
Python's docs 참조 SortedCollection하지만 thread-safe (확실합니까?)가 확실하지 않습니다.
구현이없는 경우 어떻게 구현합니까?스레드로부터 안전한 정렬 된 컬렉션
답변
Python은 Java와 다릅니다. 클래스가 문서에서 스레딩 동작을 지정하지 않은 경우 스레드 안전하다고 가정하는 것이 안전합니다.
파이썬은 스레딩을 염두에두고 작성되지 않았습니다. 오늘날에도 멀티 스레드는 실제로는 항상 단일 스레드 만 활성화되므로 (대부분의 데이터 경쟁 문제를 방지하지는 못합니다) 2 등급 시민입니다. 이를 GIL (Global Interpreter Lock)이라고합니다.
클래스 또는 데이터 구조가 동시성을 위해 구축되어 있지 않은 경우
, 당신은 코드를 통해 찾고 external lock실제로 자바와 전혀 다른 것은 아니다. 자바에서는 쓰레딩에 관해 언급 된 것이 없다면 쓰레드에 안전하지 않다고 가정하는 것이 안전합니다. 파이썬과는 달리 스레드 안전 콜렉션을 얻을 수 있습니다. 파이썬은 슬프게도 다음과 같은 점에서 부족합니다 :/ – Voo
하여 액세스를 보호해야한다, 스레드 안전 표시되지 않습니다. 여러 스레드에서 사용하려면 액세스하는 응용 프로그램 코드가 세마포 잠금 장치로 보호되어야합니다.
SortedCollection 클래스를 스레드로부터 안전하게 만들려면 데코레이터 기능을 작성할 수 있습니다.
그것은 다음과 같이 보일 것입니다 :
SortedCollection : 스레드 세이프 데이터 구조는 응용 프로그램 코드 스레드를 만들 것입니다 생각의 실수를하지 마십시오
def __init__(self):
self.mysemaphore = threading.Semaphore()
def guard(func):
def guarded(*args, **kwds):
self.mysemaphore.acquire()
try:
return func(*args, **kwds)
finally:
self.mysemaphore.release()
return guarded
# edit the class, applying the decorator to its methods.
@guard
def unsafeFunc(self, a, b, c):
''' do work here'''
편집
안전한. SortedCollection에서 여러 작업을 수행하는 경우 해당 작업을 모두 잠금으로 보호해야합니다. SortedCollection가 스레드 경우에도
다음 코드는되지 않을 것 :slist.insert(1)
slist.insert(2)
다른 스레드가 그 두 문 사이에있는 항목을 삽입 할 수있다. 애플리케이션 코드 내에서 경계해야합니다. 이 값을 응용 프로그램 코드에 추가하면 SortedCollection을 스레드로부터 안전하게 보호 할 필요가 없습니다.
semaphore2.acquire()
try:
slist.insert(1)
slist.insert(2)
finally:
semaphore2.release()
collections.OrderedDict 클래스는 업데이트가 스레드 안전하지 않습니다. 동시 읽기는 할 수 있지만 쓰기에는 잠금이 필요합니다. 과 함께 잠금을 사용하는 방법에 대한 예는 functools.lru_cache()의 출처를 참조하십시오.
heapq 모듈을 사용하여 정렬 된 목록을 유지 관리 할 수 있습니다. GIL의 힘으로 C 확장에 대한 모든 호출은 원자 적입니다 (확장이 명시 적으로 잠금을 해제하지 않는 한 CPython에서) 따라서 heappush
과 친구들은 스레드로부터 안전합니다.
from heapq import heappush, heappop
class Heap:
def __init__(self):
self._heap = []
def push(self, x):
heappush(self._heap, x)
def pop(self):
return heappop(self.heap)
...'heapq'는 _not_ C 확장자입니다 !! 'heapq'는 순수 파이썬으로 구현됩니다. [코드] (http://hg.python.org/cpython/file/2.7/Lib/heapq.py)를 확인하십시오. 빠른보기에서'heapq'는 쓰레드를 안전하게 볼 수 없습니다! – Russ
'heapq' 함수 자체가 스레드로부터 안전하지는 않지만 확실히 추가해야합니다. [Queue] (http://docs.python.org/library/queue.html) 모듈의 [PriorityQueue] (http : //docs.python.org/library/queue.html#Queue.PriorityQueue), 이는 스레드 안전하고 내부적으로'heapq'를 사용합니다. – Russ
원자 연산은 항상 파이썬에서 스레드로부터 안전합니다. 조작이 원자 적이지 않은 경우에만 동기화해야합니다. GIL은 스레드의 수에 관계없이 한 번에 하나의 원자 적 연산만을 허용합니다. 파이썬에서 다중 처리는 또 다른 문제입니다.
사실 파이썬에 왜 그런 클래스가 내장되어 있지 않은지 모르겠다. – Jonathan