Python 으로 읽 기와 쓰기 자물쇠 의 예제 코드 를 실현 합 니 다.

시작 하 다
Python 이 제공 하 는 다 중 스 레 드 모델 에 서 는 읽 기와 쓰기 자 물 쇠 를 제공 하지 않 았 습 니 다.읽 기와 쓰기 자 물 쇠 는 단순 한 상호 배척 자물쇠 보다 적용 성 이 높 습 니 다.여러 스 레 드 가 읽 기 모드 의 읽 기와 쓰기 자 물 쇠 를 동시에 사용 할 수 있 지만 한 스 레 드 만 쓰기 모드 의 읽 기와 쓰기 자 물 쇠 를 사용 할 수 있 습 니 다.
쉽게 말 하면 자 물 쇠 를 쓰 지 않 았 을 때 자 물 쇠 를 읽 을 수 있 고 임 의 스 레 드 를 동시에 추가 할 수 있다 는 것 이다.자 물 쇠 는 하나의 스 레 드 만 있 을 수 있 고 자 물 쇠 를 읽 지 않 았 을 때 만 추가 할 수 있 습 니 다.
단순 한 실현

import threading

class RWlock(object):
  def __init__(self):
    self._lock = threading.Lock()
    self._extra = threading.Lock()
    self.read_num = 0

  def read_acquire(self):
    with self._extra:
      self.read_num += 1
      if self.read_num == 1:
        self._lock.acquire()

  def read_release(self):
    with self._extra:
      self.read_num -= 1
      if self.read_num == 0:
        self._lock.release()

  def write_acquire(self):
    self._lock.acquire()

  def write_release(self):
    self._lock.release()
이것 은 읽 기와 쓰기 자물쇠 의 간단 한 실현 입 니 다.self.readnum 은 읽 기 자 물 쇠 를 얻 은 스 레 드 수 를 저장 하 는 데 사 용 됩 니 다.이 속성 은 임계 구역 에 속 하고 그 조작 에 도 자 물 쇠 를 추가 해 야 하기 때문에 내부 데 이 터 를 보호 하 는 추가 자물쇠 self 가 필요 합 니 다.extra 。
하지만 이 자 물 쇠 는 불공평 하 다.이상 적 인 상황 에서 스 레 드 가 얻 은 기 회 는 똑 같 아야 한다.스 레 드 가 읽 기 동작 이 든 쓰기 동작 이 든.상기 코드 에서 볼 수 있 듯 이 읽 기 요청 은 self.read 를 즉시 설정 합 니 다.num+=1,자 물 쇠 를 얻 었 든 안 얻 었 든 간 에 자 물 쇠 를 얻 으 려 면 read 를 기 다 려 야 합 니 다.num 은 0 이다.
그래서 이 로 인해 자물쇠 만 점용 되 지 않 거나 읽 기 요청 이 없 을 때 쓰기 권한 을 얻 을 수 있 습 니 다.우 리 는 읽 기 모드 자물쇠 가 장기 적 으로 점용 되 는 것 을 피 할 방법 을 생각해 야 한다.
읽 기와 쓰기 자물쇠 의 우선 순위
읽 기와 쓰기 자물쇠 도 읽 기 우선 과 쓰기 우선 이 있다.위의 코드 는 읽 기 우선 에 속한다.
쓰기 우선 순위 로 바 꾸 려 면 쓰기 스 레 드 의 인용 수 를 기록 하 는 것 으로 바 꾸 고 읽 기와 쓰기 가 동시에 경쟁 할 때 쓰기 스 레 드 에 쓰기 수 를 늘 릴 수 있 습 니 다.그러면 읽 기 스 레 드 의 읽 기 자 물 쇠 를 계속 얻 지 못 할 수 있 습 니 다.읽 기 스 레 드 는 먼저 쓴 인용 수 를 판단 하고 0 이 아니라면 0 을 기다 린 다음 에 읽 어야 하기 때 문 입 니 다.이 부분의 코드 는 나열 되 지 않 는 다.
그러나 이 는 분명 융통성 이 없다.우 리 는 비슷 한 읽 기와 쓰기 자물쇠 류 두 개 를 필요 로 하지 않 는 다.우 리 는 우리 코드 를 재 구성 해서 그것 을 더욱 강하 게 하 기 를 바란다.
개선 하 다.
사용자 정의 우선 순위 읽 기와 쓰기 자 물 쇠 를 만족 시 키 기 위해 서 는 기다 리 는 읽 기와 쓰기 스 레 드 수 를 기록 하고 두 가지 조건 이 필요 합 니 다.threading.Condition 은 어느 쪽 이 우선 인지 알려 줍 니 다.계수 인용 은 의 미 를 확대 할 수 있 습 니 다:정수:작업 을 읽 고 있 는 스 레 드 수 를 표시 합 니 다.마이너스:작업 을 쓰 고 있 는 스 레 드 수(최대-1)를 표시 합 니 다.
읽 기 동작 을 가 져 올 때 먼저 판단 할 때 기다 리 는 쓰기 스 레 드 가 있 습 니 다.없 으 면 읽 기 동작 을 하고 있 으 면 읽 기 를 기다 리 는 계수 가 1 을 더 한 후에 Condition 알림 을 기다 리 고 있 습 니 다.읽 기 를 기다 리 는 계수 가 1 을 줄 이 고 인용 에 1 을 추가 하 며 계속 읽 기 작업 을 합 니 다.조건 이 성립 되 지 않 으 면 반복 적 으로 기다 립 니 다.
쓰기 동작 을 가 져 올 때 잠 금 이 점용 되 지 않 으 면 인용 계수 가 1 을 줄 이 고 점용 되면 쓰기 스 레 드 수 에 1 을 추가 하고 쓰기 조건 Condition 의 통 지 를 기다 리 십시오.
읽 기 모드 와 쓰기 모드 의 방출 은 모두 같 으 므 로 판단 에 따라 대응 하 는 Condition 을 알려 야 합 니 다.

class RWLock(object):
  def __init__(self):
    self.lock = threading.Lock()
    self.rcond = threading.Condition(self.lock)
    self.wcond = threading.Condition(self.lock)
    self.read_waiter = 0  #           
    self.write_waiter = 0  #           
    self.state = 0     #   :               :           (  -1)
    self.owners = []    #        id  
    self.write_first = True #      ,False     

  def write_acquire(self, blocking=True):
    #        
    me = threading.get_ident()
    with self.lock:
      while not self._write_acquire(me):
        if not blocking:
          return False
        self.write_waiter += 1
        self.wcond.wait()
        self.write_waiter -= 1
    return True

  def _write_acquire(self, me):
    #             ,          
    if self.state == 0 or (self.state < 0 and me in self.owners):
      self.state -= 1
      self.owners.append(me)
      return True
    if self.state > 0 and me in self.owners:
      raise RuntimeError('cannot recursively wrlock a rdlocked lock')
    return False

  def read_acquire(self, blocking=True):
    me = threading.get_ident()
    with self.lock:
      while not self._read_acquire(me):
        if not blocking:
          return False
        self.read_waiter += 1
        self.rcond.wait()
        self.read_waiter -= 1
    return True

  def _read_acquire(self, me):
    if self.state < 0:
      #         
      return False

    if not self.write_waiter:
      ok = True
    else:
      ok = me in self.owners
    if ok or not self.write_first:
      self.state += 1
      self.owners.append(me)
      return True
    return False

  def unlock(self):
    me = threading.get_ident()
    with self.lock:
      try:
        self.owners.remove(me)
      except ValueError:
        raise RuntimeError('cannot release un-acquired lock')

      if self.state > 0:
        self.state -= 1
      else:
        self.state += 1
      if not self.state:
        if self.write_waiter and self.write_first:  #          (     )
          self.wcond.notify()
        elif self.read_waiter:
          self.rcond.notify_all()
        elif self.write_waiter:
          self.wcond.notify()

  read_release = unlock
  write_release = unlock

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기