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

用Python實現(xiàn)讀寫鎖的示例代碼

 更新時間:2018年11月05日 09:25:41   作者:weapon  
這篇文章主要介紹了用Python實現(xiàn)讀寫鎖的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

起步

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

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

簡單的實現(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ū),對其操作也要加鎖,所以這里需要一個保護(hù)內(nèi)部數(shù)據(jù)的額外的鎖 self._extra 。

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

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

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

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

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

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

改進(jìn)

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

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

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

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

  def write_acquire(self, blocking=True):
    # 獲取寫鎖只有當(dāng)
    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):
    # 獲取寫鎖只有當(dāng)鎖沒人占用,或者當(dāng)前線程已經(jīng)占用
    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:  # 如果有寫操作在等待(默認(rèn)寫優(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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python如何將兩個Excel文件按相同字段合并到一起

    Python如何將兩個Excel文件按相同字段合并到一起

    文章介紹了如何使用Pandas工具將兩個關(guān)聯(lián)的Excel文件合并成一個,首先創(chuàng)建兩個Excel文件test1和test2,然后使用Pandas進(jìn)行合并,最后顯示新創(chuàng)建的Excel文件
    2025-02-02
  • python實現(xiàn)圖像識別功能

    python實現(xiàn)圖像識別功能

    這篇文章主要為大家詳細(xì)介紹了python實現(xiàn)圖像識別功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Python實現(xiàn)的遠(yuǎn)程登錄windows系統(tǒng)功能示例

    Python實現(xiàn)的遠(yuǎn)程登錄windows系統(tǒng)功能示例

    這篇文章主要介紹了Python實現(xiàn)的遠(yuǎn)程登錄windows系統(tǒng)功能,結(jié)合實例形式分析了Python基于wmi模塊的遠(yuǎn)程連接與進(jìn)程操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2018-06-06
  • Python爬蟲實戰(zhàn)之使用Scrapy爬取豆瓣圖片

    Python爬蟲實戰(zhàn)之使用Scrapy爬取豆瓣圖片

    在用Python的urllib和BeautifulSoup寫過了很多爬蟲之后,本人決定嘗試著名的Python爬蟲框架——Scrapy.本次分享將詳細(xì)講述如何利用Scrapy來下載豆瓣名人圖片,需要的朋友可以參考下
    2021-06-06
  • Pycharm同步遠(yuǎn)程服務(wù)器調(diào)試的方法步驟

    Pycharm同步遠(yuǎn)程服務(wù)器調(diào)試的方法步驟

    這篇文章主要介紹了Pycharm同步遠(yuǎn)程服務(wù)器調(diào)試,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Pandas處理時間序列數(shù)據(jù)操作詳解

    Pandas處理時間序列數(shù)據(jù)操作詳解

    這篇文章主要介紹了Pandas處理時間序列數(shù)據(jù)操作詳解,文章首先利用python自帶datetime庫,通過調(diào)用此庫可以獲取本地時間展開內(nèi)容說明具有一定的參考價值,需要的小伙伴可以參考一下
    2022-06-06
  • 最新評論

    江口县| 玉溪市| 上犹县| 高邑县| 靖边县| 宿松县| 张家口市| 广昌县| 天峨县| 辛集市| 隆回县| 镇巴县| 陇川县| 阿图什市| 青阳县| 安阳县| 即墨市| 古蔺县| 深水埗区| 东光县| 密山市| 辛集市| 礼泉县| 烟台市| 太谷县| 油尖旺区| 湄潭县| 靖江市| 农安县| 平谷区| 台湾省| 大英县| 鄂托克旗| 无极县| 松原市| 社会| 石泉县| 东海县| 米泉市| 太仆寺旗| 屏山县|