2011-10-25 3 views

답변

1

Python은 Java와 다릅니다. 클래스가 문서에서 스레딩 동작을 지정하지 않은 경우 스레드 안전하다고 가정하는 것이 안전합니다.

파이썬은 스레딩을 염두에두고 작성되지 않았습니다. 오늘날에도 멀티 스레드는 실제로는 항상 단일 스레드 만 활성화되므로 (대부분의 데이터 경쟁 문제를 방지하지는 못합니다) 2 등급 시민입니다. 이를 GIL (Global Interpreter Lock)이라고합니다.

클래스 또는 데이터 구조가 동시성을 위해 구축되어 있지 않은 경우

, 당신은 코드를 통해 찾고 external lock

+0

실제로 자바와 전혀 다른 것은 아니다. 자바에서는 쓰레딩에 관해 언급 된 것이 없다면 쓰레드에 안전하지 않다고 가정하는 것이 안전합니다. 파이썬과는 달리 스레드 안전 콜렉션을 얻을 수 있습니다. 파이썬은 슬프게도 다음과 같은 점에서 부족합니다 :/ – Voo

3

하여 액세스를 보호해야한다, 스레드 안전 표시되지 않습니다. 여러 스레드에서 사용하려면 액세스하는 응용 프로그램 코드가 세마포 잠금 장치로 보호되어야합니다.

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

func return이 세마포어 릴리스를 차단하지 않습니까? – Eduardo

+1

@eduardocereto docs :'try 절의 다른 절이 중단, 계속 또는 return 문을 통해 남아있을 때 finally 절이 "중간에"실행됩니다. ' – rplnt

+0

데코레이터의 놀라운 사용! –

1

collections.OrderedDict 클래스는 업데이트가 스레드 안전하지 않습니다. 동시 읽기는 할 수 있지만 쓰기에는 잠금이 필요합니다. 과 함께 잠금을 사용하는 방법에 대한 예는 functools.lru_cache()의 출처를 참조하십시오.

0

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) 
+0

...'heapq'는 _not_ C 확장자입니다 !! 'heapq'는 순수 파이썬으로 구현됩니다. [코드] (http://hg.python.org/cpython/file/2.7/Lib/heapq.py)를 확인하십시오. 빠른보기에서'heapq'는 쓰레드를 안전하게 볼 수 없습니다! – Russ

+4

'heapq' 함수 자체가 스레드로부터 안전하지는 않지만 확실히 추가해야합니다. [Queue] (http://docs.python.org/library/queue.html) 모듈의 [PriorityQueue] (http : //docs.python.org/library/queue.html#Queue.PriorityQueue), 이는 스레드 안전하고 내부적으로'heapq'를 사용합니다. – Russ

0

원자 연산은 항상 파이썬에서 스레드로부터 안전합니다. 조작이 원자 적이지 않은 경우에만 동기화해야합니다. GIL은 스레드의 수에 관계없이 한 번에 하나의 원자 적 연산만을 허용합니다. 파이썬에서 다중 처리는 또 다른 문제입니다.