2011-12-13 6 views
5

Python에서 실행중인 웹 서버가 있습니다. 서버는 비공개이므로 약 20 명의 사용자 만 연결할 수 있습니다. 서버는 멀티 스레드 (현재 8 코어, 그래서 내가 생각한 8 스레드)입니다.이 파이썬 사전은 쓰레드에 안전합니까?

요청이 들어 오면 사용자를 식별 할 수 있습니다. 일부 쿼리에서는 사용자 이름 -> 부울 형태의 간단한 dictionary을 업데이트해야합니다. 이 스레드를 안전하게 만들려면 어떻게해야합니까?

+0

직접 서버를 구현하거나 장고, 피라미드 또는 꼬인 것을 사용하고 있습니까? – dirk

+0

그것은 체리 피, 버전 3.2 – Jerome

답변

5

있습니다 (경쟁 조건 투입 Joonas 설명을 피하기 위해) 잠금을해야하고,이 작업이 원자이기 때문에,

import threading 
lock = threading.Lock() 

shared_dict = {} 

def do_thing(user, value): 
    lock.acquire() 
    try: 
     shared_dict[user] = value 
    finally: 
     # Always called, even if exception is raised in try block 
     lock.release() 
+0

내 작가가 수정 내용을 해당 자물쇠로 감쌌다 고 가정 해 봅시다. 리더가 릴리스 될 때까지 기다릴 것인가, 즉 쓰기가 끝났습니까? 아니면 그걸 읽어야합니까? – Jerome

+0

@ jeromeG 아마도 "읽기 - 수정 - 쓰기"경쟁 조건을 피하기 위해 비슷한 잠금 기능이 있어야 할 것입니다. – dbr

2

사전을 업데이트하기 전에 threading.LOCK.acquire()을 사용하고 업데이트를 완료하면 threading.LOCK.release()를 사용하십시오.

+0

이것은 이상하다, 나는 잠금 개체가 사전에 특정 될 것이라고 예상했었다. 자바에서 동기화 된 객체/블록/메소드와 조금 비슷했다 ... 나는 혼란 스럽다. – Jerome

8

전역 잠금 개체를 만들어야합니다.

lock = threading.Lock() 

그런 다음 사전을 액세스 할 때마다 잠금을 획득하고 해제합니다. 가장 간단한 방법은 새로운 (ish) with syntax입니다.

with lock: 
    dict[key] = value 
+0

나는 제한되어있다. 파이썬 2.4의 사용은 가능하지 않을까요? – Jerome

+0

아니요, with는 사용할 수 없지만 대신 lock.acquire() 및 lock.release()를 사용할 수 있습니다. –

4

당신은 나 Boolean 업데이트 방식에 따라 잠금을 사용하지 않을 수 있습니다. 쓰기와 파이썬 사전을 읽는 스레드 안전을 제외하고 자체 (기준입니다 : 다음 Boolean의 값이되지이 이전 값에 따라 달라집니다 않는 경우

는, 다음에는 잠금이 필요하지 않습니다 writing while iterating is not allowed -하지만이 하나에 허용하지 않는다 스레드 중 하나). 메모리 가시성은 일부 언어에서 volatile을 사용하여 얻을 수있는 것과 유사합니다.

기본적으로 스레드로부터 안전하지 않은 것은 "읽기 - 수정 - 쓰기"시퀀스이며 경쟁 조건이됩니다. Boolean의 값이 인 경우 이전 값에 따라 다르고 그렇지 않으면 잠금을 사용해야합니다. 그렇지 않으면 스레드 A가 먼저 값을 읽을 수 있고 그러면 스레드 B가 값을 변경할 수 있으므로 A가 다시 값을 변경할 수 있기 때문입니다. 오래된 가치.

0

당신은이 작업에 사전을 잠글 필요하지는 파이썬 2.4와 함께 붙어있는 경우 , 그리고 GIL이 당신을 위해 이것을 돌 봅니다. 읽기 - 쓰기 - 쓰기와 같은 작업이 없으면 걱정하지 마십시오.

관련 문제