欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

起步

Python 提供的多線程模型中并沒(méi)有提供讀寫鎖,讀寫鎖相對(duì)于單純的互斥鎖,適用性更高,可以多個(gè)線程同時(shí)占用讀模式的讀寫鎖,但是只能一個(gè)線程占用寫模式的讀寫鎖。

通俗點(diǎn)說(shuō)就是當(dāng)沒(méi)有寫鎖時(shí),就可以加讀鎖且任意線程可以同時(shí)加;而寫鎖只能有一個(gè)線程,且必須在沒(méi)有讀鎖時(shí)才能加上。

簡(jiǎn)單的實(shí)現(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()

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

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

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

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

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

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

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

改進(jìn)

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

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

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

讀模式和寫模式的釋放都是一樣,需要根據(jù)判斷去通知對(duì)應(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)鎖沒(méi)人占用,或者當(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

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

相關(guān)文章

  • Python中g(shù)lob庫(kù)實(shí)現(xiàn)文件名的匹配

    Python中g(shù)lob庫(kù)實(shí)現(xiàn)文件名的匹配

    本文主要主要介紹了Python中g(shù)lob庫(kù)實(shí)現(xiàn)文件名的匹配,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • Python一行代碼實(shí)現(xiàn)ChatGPT接入微信機(jī)器人

    Python一行代碼實(shí)現(xiàn)ChatGPT接入微信機(jī)器人

    這篇文章主要為大家介紹了Python一行代碼實(shí)現(xiàn)ChatGPT接入微信機(jī)器人示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • python中函數(shù)的返回值及類型詳解

    python中函數(shù)的返回值及類型詳解

    這篇文章主要為大家介紹了python中函數(shù)的返回值及類型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Keras使用預(yù)訓(xùn)練模型遷移學(xué)習(xí)單通道灰度圖像詳解

    Keras使用預(yù)訓(xùn)練模型遷移學(xué)習(xí)單通道灰度圖像詳解

    這篇文章主要介紹了Keras使用預(yù)訓(xùn)練模型遷移學(xué)習(xí)單通道灰度圖像詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Python基礎(chǔ)之輸入,輸出與高階賦值詳解

    Python基礎(chǔ)之輸入,輸出與高階賦值詳解

    這篇文章主要為大家介紹了Python基礎(chǔ)之輸入,輸出與高階賦值,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-11-11
  • 十分鐘利用Python制作屬于你自己的個(gè)性logo

    十分鐘利用Python制作屬于你自己的個(gè)性logo

    這篇文章主要給大家介紹了關(guān)于十分鐘如何利用Python制作屬于你自己的個(gè)性logo的相關(guān)資料,主要利用的是詞云實(shí)現(xiàn)這個(gè)效果,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友下面來(lái)一起看看吧
    2018-05-05
  • python根據(jù)經(jīng)緯度計(jì)算距離示例

    python根據(jù)經(jīng)緯度計(jì)算距離示例

    這篇文章主要介紹了python根據(jù)經(jīng)緯度計(jì)算距離示例, 計(jì)算兩點(diǎn)之間距離,需要的朋友可以參考下
    2014-02-02
  • TensorFlow tf.nn.conv2d實(shí)現(xiàn)卷積的方式

    TensorFlow tf.nn.conv2d實(shí)現(xiàn)卷積的方式

    今天小編就為大家分享一篇TensorFlow tf.nn.conv2d實(shí)現(xiàn)卷積的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-01-01
  • Python button選取本地圖片并顯示的實(shí)例

    Python button選取本地圖片并顯示的實(shí)例

    今天小編就為大家分享一篇Python button選取本地圖片并顯示的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-06-06
  • 詳解Django自定義圖片和文件上傳路徑(upload_to)的2種方式

    詳解Django自定義圖片和文件上傳路徑(upload_to)的2種方式

    這篇文章主要介紹了詳解Django自定義圖片和文件上傳路徑(upload_to)的2種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評(píng)論