最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python讀寫鎖實現(xiàn)實現(xiàn)代碼解析

 更新時間:2020年11月28日 08:38:16   作者:-零  
這篇文章主要介紹了Python讀寫鎖實現(xiàn)實現(xiàn)代碼解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

起步

Python 提供的多線程模型中并沒有提供讀寫鎖,讀寫鎖相對于單純的互斥鎖,適用性更高,可以多個線程同時占用讀模式的讀寫鎖,但是只能一個線程占用寫模式的讀寫鎖。

通俗點說就是當沒有寫鎖時,就可以加讀鎖且任意線程可以同時加;而寫鎖只能有一個線程,且必須在沒有讀鎖時才能加上。

簡單的實現(xiàn)

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

這是讀寫鎖的一個簡單的實現(xiàn),self.read_num 用來保存獲得讀鎖的線程數(shù),這個屬性屬于臨界區(qū),對其操作也要加鎖,所以這里需要一個保護內部數(shù)據(jù)的額外的鎖 self._extra 。

但是這個鎖是不公平的。理想情況下,線程獲得所的機會應該是一樣的,不管線程是讀操作還是寫操作。而從上述代碼可以看到,讀請求都會立即設置 self.read_num += 1,不管有沒有獲得鎖,而寫請求想要獲得鎖還得等待 read_num 為 0 。

所以這個就造成了只有鎖沒有被占用或者沒有讀請求時,可以獲得寫權限。我們應該想辦法避免讀模式鎖長期占用。

讀寫鎖的優(yōu)先級

讀寫鎖也有分 讀優(yōu)先 和 寫優(yōu)先。上面的代碼就屬于讀優(yōu)先。

如果要改成寫優(yōu)先,那就換成去記錄寫線程的引用計數(shù),讀和寫在同時競爭時,可以讓寫線程增加寫的計數(shù),這樣可使讀線程的讀鎖一直獲取不到, 因為讀線程要先判斷寫的引用計數(shù),若不為0,則等待其為 0,然后進行讀。這部分代碼不羅列了。

但這樣顯然不夠靈活。我們不需要兩個相似的讀寫鎖類。我們希望重構我們代碼,使它更強大。

改進

為了能夠滿足自定義優(yōu)先級的讀寫鎖,要記錄等待的讀寫線程數(shù),并且需要兩個條件 threading.Condition 用來處理哪方優(yōu)先的通知。計數(shù)引用可以擴大語義:正數(shù):表示正在讀操作的線程數(shù),負數(shù):表示正在寫操作的線程數(shù)(最多-1)

在獲取讀操作時,先然后判斷時候有等待的寫線程,沒有,進行讀操作,有,則等待讀的計數(shù)加 1 后等待 Condition 通知;等待讀的計數(shù)減 1,計數(shù)引用加 1,繼續(xù)讀操作,若條件不成立,循環(huán)等待;

在獲取寫操作時,若鎖沒有被占用,引用計數(shù)減 1,若被占用,等待寫線程數(shù)加 1,等待寫條件 Condition 的通知。

讀模式和寫模式的釋放都是一樣,需要根據(jù)判斷去通知對應的 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  # 等待獲取讀鎖的線程數(shù)
    self.write_waiter = 0  # 等待獲取寫鎖的線程數(shù)
    self.state = 0     # 正數(shù):表示正在讀操作的線程數(shù)  負數(shù):表示正在寫操作的線程數(shù)(最多-1)
    self.owners = []    # 正在操作的線程id集合
    self.write_first = True # 默認寫優(yōu)先,F(xiàn)alse表示讀優(yōu)先

  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:  # 如果有寫操作在等待(默認寫優(yōu)先)
          self.wcond.notify()
        elif self.read_waiter:
          self.rcond.notify_all()
        elif self.write_waiter:
          self.wcond.notify()

  read_release = unlock
  write_release = unlock

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Python連接DB2數(shù)據(jù)庫

    Python連接DB2數(shù)據(jù)庫

    DB2 是美國IBM公司開發(fā)的一套關系型數(shù)據(jù)庫管理系統(tǒng),它主要的運行環(huán)境為UNIX(包括IBM自家的AIX)、Linux、IBM i(舊稱OS/400)、z/OS,以及Windows服務器版本。今天我們來探討下如何使用Python連接DB2數(shù)據(jù)庫
    2016-08-08
  • Python+OpenCV圖像處理——實現(xiàn)直線檢測

    Python+OpenCV圖像處理——實現(xiàn)直線檢測

    這篇文章主要介紹了Python+OpenCV如何實現(xiàn)直線檢測,幫助大家更好的利用python處理圖片,感興趣的朋友可以了解下
    2020-10-10
  • Python中的CSV文件使用

    Python中的CSV文件使用"with"語句的方式詳解

    with語句的主要用法是對語句中使用的對象進行異常安全的清除.確保文件已關閉,鎖定已釋放,上下文恢復等.本文通過實例代碼給大家介紹Python中的CSV文件使用"with"語句的相關知識,感興趣的朋友一起看看吧
    2018-10-10
  • cuda突然不能用了的完美解決方法

    cuda突然不能用了的完美解決方法

    這篇文章主要給大家介紹了關于cuda突然不能用了的完美解決方法,文中通過圖文介紹的非常詳細,對大家學習或者使用cuda具有一定的參考學習價值,需要的朋友可以參考下
    2023-06-06
  • python之如何實現(xiàn)延遲操作

    python之如何實現(xiàn)延遲操作

    這篇文章主要介紹了python之如何實現(xiàn)延遲操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • pytorch:torch.mm()和torch.matmul()的使用

    pytorch:torch.mm()和torch.matmul()的使用

    今天小編就為大家分享一篇pytorch:torch.mm()和torch.matmul()的使用,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • Python批量解壓&壓縮文件夾的示例代碼

    Python批量解壓&壓縮文件夾的示例代碼

    這篇文章主要介紹了利用Python實現(xiàn)批量解壓&壓縮文件夾的示例代碼,文中的實現(xiàn)步驟講解詳細,感興趣的小伙伴快跟隨小編一起動手試一試
    2022-04-04
  • 翻轉數(shù)列python實現(xiàn),求前n項和,并能輸出整個數(shù)列的案例

    翻轉數(shù)列python實現(xiàn),求前n項和,并能輸出整個數(shù)列的案例

    這篇文章主要介紹了翻轉數(shù)列python實現(xiàn),求前n項和,并能輸出整個數(shù)列的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • Python 一鍵獲取百度網(wǎng)盤提取碼的方法

    Python 一鍵獲取百度網(wǎng)盤提取碼的方法

    這篇文章主要介紹了Python 一鍵獲取百度網(wǎng)盤提取碼的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • python3.8與pyinstaller沖突問題的快速解決方法

    python3.8與pyinstaller沖突問題的快速解決方法

    這篇文章主要介紹了python3.8與pyinstaller沖突問題及解決方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01

最新評論

武城县| 马关县| 化德县| 金川县| 庄河市| 梅河口市| 鹤峰县| 新兴县| 天峻县| 柳州市| 辽源市| 固镇县| 延寿县| 米泉市| 英吉沙县| 伽师县| 延庆县| 山西省| 南皮县| 吐鲁番市| 渭源县| 富宁县| 扶绥县| 绥芬河市| 唐海县| 仪陇县| 海南省| 邻水| 通山县| 大厂| 四会市| 尚志市| 江津市| 建湖县| 珠海市| 北辰区| 济阳县| 五寨县| 团风县| 贵德县| 枣阳市|