Python 잠 금 방지 방법
다 중 스 레 드 프로그램 을 쓰 고 있 습 니 다.스 레 드 는 한 번 에 여러 개의 자 물 쇠 를 가 져 와 야 합 니 다.이 때 잠 금 문 제 를 어떻게 피 할 수 있 습 니까?
해결 방안
다 중 스 레 드 프로그램 에서 잠 금 문제 의 큰 부분 은 스 레 드 가 여러 개의 자 물 쇠 를 동시에 가 져 오기 때 문 입 니 다.예 를 들 어 하나의 스 레 드 가 첫 번 째 자 물 쇠 를 가 져 온 다음 에 두 번 째 자 물 쇠 를 가 져 올 때 차단 이 발생 하면 이 스 레 드 는 다른 스 레 드 의 실행 을 막 아서 전체 프로그램 이 가사 할 수 있 습 니 다.잠 금 문 제 를 해결 하 는 방안 은 프로그램의 모든 잠 금 에 유일한 id 를 분배 한 다음 에 오름차 규칙 에 따라 여러 개의 잠 금 만 사용 할 수 있 도록 하 는 것 입 니 다.이 규칙 은 문맥 관리 자 를 사용 하 는 것 이 매우 쉽 습 니 다.예 를 들 어 다음 과 같 습 니 다.
import threading
from contextlib import contextmanager
# Thread-local state to stored information on locks already acquired
_local = threading.local()
@contextmanager
def acquire(*locks):
# Sort locks by object identifier
locks = sorted(locks, key=lambda x: id(x))
# Make sure lock order of previously acquired locks is not violated
acquired = getattr(_local,'acquired',[])
if acquired and max(id(lock) for lock in acquired) >= id(locks[0]):
raise RuntimeError('Lock Order Violation')
# Acquire all of the locks
acquired.extend(locks)
_local.acquired = acquired
try:
for lock in locks:
lock.acquire()
yield
finally:
# Release locks in reverse order of acquisition
for lock in reversed(locks):
lock.release()
del acquired[-len(locks):]
이 상하 문 관리 자 를 어떻게 사용 합 니까?정상 적 인 경로 에 따라 자물쇠 대상 을 만 들 수 있 지만 하나의 자물쇠 든 여러 개의 자물쇠 든acquire()
함수 로 자 물 쇠 를 신청 할 수 있 습 니 다.예 를 들 어 다음 과 같 습 니 다.
import threading
x_lock = threading.Lock()
y_lock = threading.Lock()
def thread_1():
while True:
with acquire(x_lock, y_lock):
print('Thread-1')
def thread_2():
while True:
with acquire(y_lock, x_lock):
print('Thread-2')
t1 = threading.Thread(target=thread_1)
t1.daemon = True
t1.start()
t2 = threading.Thread(target=thread_2)
t2.daemon = True
t2.start()
이 코드 를 실행 하면 서로 다른 함수 에서 다른 순서 로 자 물 쇠 를 가 져 와 도 잠 금 이 발생 하지 않 는 다 는 것 을 알 게 될 것 입 니 다.첫 번 째 코드 에서 우 리 는 이 자물쇠 들 을 정렬 하 는 것 이 관건 이다.정렬 을 통 해 사용자 가 어떤 순서 로 자 물 쇠 를 요청 하 든 이 자 물 쇠 는 고정된 순서에 따라 가 져 옵 니 다.여러 acquire()작업 이 내장 되 어 호출 되면 스 레 드 로 컬 저장 소(TLS)를 통 해 잠재 적 인 잠 금 문 제 를 감지 할 수 있 습 니 다.만약 당신 의 코드 가 이렇게 쓰 여 있다 면:
import threading
x_lock = threading.Lock()
y_lock = threading.Lock()
def thread_1():
while True:
with acquire(x_lock):
with acquire(y_lock):
print('Thread-1')
def thread_2():
while True:
with acquire(y_lock):
with acquire(x_lock):
print('Thread-2')
t1 = threading.Thread(target=thread_1)
t1.daemon = True
t1.start()
t2 = threading.Thread(target=thread_2)
t2.daemon = True
t2.start()
이 버 전의 코드 를 실행 하면 스 레 드 가 무 너 질 것 입 니 다.이상 한 정 보 는 다음 과 같 을 수 있 습 니 다.
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/local/lib/python3.3/threading.py", line 639, in _bootstrap_inner
self.run()
File "/usr/local/lib/python3.3/threading.py", line 596, in run
self._target(*self._args, **self._kwargs)
File "deadlock.py", line 49, in thread_1
with acquire(y_lock):
File "/usr/local/lib/python3.3/contextlib.py", line 48, in __enter__
return next(self.gen)
File "deadlock.py", line 15, in acquire
raise RuntimeError("Lock Order Violation")
RuntimeError: Lock Order Violation
>>>
붕괴 의 원인 은 모든 스 레 드 에 자신 이 가 져 온 자 물 쇠 를 기록 하고 있 기 때문이다.acquire()함 수 는 이전에 가 져 온 자물쇠 목록 을 검사 합 니 다.자 물 쇠 는 오름차 순 으로 배열 되 어 있 기 때문에 함 수 는 이전에 가 져 온 자물쇠 의 id 가 새로 신청 한 자물쇠 보다 작 을 것 이 라 고 생각 합 니 다.이 때 이상 이 발생 합 니 다.토론 하 다.
잠 금 은 모든 다 중 스 레 드 프로그램 이 직면 하 는 문제 이다.경험 에 의 하면 가능 한 한 모든 라인 이 하나의 자물쇠 만 동시에 유지 할 수 있 도록 보장 하면 프로그램 이 자물쇠 문제 에 시 달리 지 않 을 것 이다.일단 스 레 드 가 있 으 면 여러 개의 자 물 쇠 를 동시에 신청 하면 모든 것 을 예측 할 수 없다.
잠 금 검사 와 복 구 는 우아 한 해결 방안 이 거의 없 는 확장 화제 이다.비교적 자주 사용 되 는 자물쇠 검사 와 복구 방안 은 문지기 계수 기 를 도입 하 는 것 이다.스 레 드 가 정상적으로 작 동 할 때 일정 시간 마다 계수 기 를 리 셋 하고 잠 금 이 발생 하지 않 은 상태 에서 모든 것 이 정상적으로 진행 된다.잠 금 이 발생 하면 계수 기 를 초기 화 할 수 없어 타이머 가 시간 을 초과 하면 프로그램 은 다시 시작 을 통 해 정상 상태 로 돌아 갑 니 다.
잠 금 을 피 하 는 것 은 또 다른 잠 금 문 제 를 해결 하 는 방식 입 니 다.프로 세 스 가 잠 금 을 가 져 올 때 대상 id 의 오름차 순 으로 엄 격 히 배열 하여 얻 을 수 있 습 니 다.수학 적 증명 을 통 해 프로그램 이 잠 금 상태 에 들 어가 지 않도록 합 니 다.증명 은 독자 에 게 연습 으로 남 겨 두 었 다.잠 금 을 피 하 는 주요 사상 은 단순히 대상 id 가 증가 하 는 순서에 따라 잠 금 을 추가 하면 순환 의존 이 발생 하지 않 고 순환 의존 은 잠 금 의 필수 조건 이 므 로 프로그램 이 잠 금 상태 에 들 어가 지 않도록 하 는 것 이다.
다음은 스 레 드 잠 금 에 관 한 전형 적 인 문제 인'철학 자 식사 문제'를 본 절의 마지막 예 로 들 겠 습 니 다.제목 은 이 렇 습 니 다.다섯 명의 철학 자가 한 테이블 앞 에 둘 러 앉 아 있 고 모든 사람 앞 에 밥 한 그릇 과 젓가락 이 있 습 니 다.여기 서 모든 철학 자 들 은 하나의 독립 된 라인 이 라 고 볼 수 있 고,젓가락 마다 하나의 자물쇠 라 고 볼 수 있다.모든 철학 자 는 정좌,사고,식사 세 가지 상태 중 하나 에 처 할 수 있다.주의해 야 할 것 은 모든 철학 자 들 이 밥 을 먹 을 때 두 개의 젓가락 이 필요 하 다 는 것 이다.이런 문 제 는 모든 철학 자 들 이 자신의 왼쪽 젓가락 을 들 면 그들 다섯 명 은 젓가락 하 나 를 들 고 굶 어 죽 을 때 까지 앉 아 있 을 수 밖 에 없다 는 것 이다.이때 그들 은 자물쇠 상태 로 들 어 갔다.다음은'철학 자 식사 문제'를 해결 하 는 간단 한 잠 금 방지 체 제 를 사용 하 는 실현 이다.
import threading
# The philosopher thread
def philosopher(left, right):
while True:
with acquire(left,right):
print(threading.currentThread(), 'eating')
# The chopsticks (represented by locks)
NSTICKS = 5
chopsticks = [threading.Lock() for n in range(NSTICKS)]
# Create all of the philosophers
for n in range(NSTICKS):
t = threading.Thread(target=philosopher,
args=(chopsticks[n],chopsticks[(n+1) % NSTICKS]))
t.start()
마지막 으로 자물쇠 가 꺼 지지 않도록 모든 자물쇠 추가 작업 은acquire()
함 수 를 사용 해 야 한 다 는 것 을 주의해 야 한다.만약 코드 중의 일부분 이 acquire 함 수 를 돌아 서 직접 자 물 쇠 를 신청한다 면 전체 자물쇠 피 하 는 메커니즘 은 작용 하지 않 을 것 이다.이상 은 Python 의 잠 금 방지 방법 에 대한 상세 한 내용 입 니 다.Python 의 잠 금 방지 에 관 한 자 료 는 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.