1. 程式人生 > 程式設計 >Python執行緒協作threading.Condition實現過程解析

Python執行緒協作threading.Condition實現過程解析

領會下面這個示例吧,其實跟java中wait/nofity是一樣一樣的道理

import threading


# 條件變數,用於複雜的執行緒間同步鎖
"""
需求:
  男:小姐姐,你好呀!
  女:哼,想泡老孃不成?
  男:對呀,想泡你
  女:滾蛋,門都沒有!
  男:切,長這麼醜,還這麼吊...
  女:關你鳥事!

"""
class Boy(threading.Thread):
  def __init__(self,name,condition):
    super().__init__(name=name)
    self.condition = condition

  def run(self):
    with self.condition:
      print("{}:小姐姐,你好呀!".format(self.name))
      self.condition.wait()
      self.condition.notify()

      print("{}:對呀,想泡你".format(self.name))
      self.condition.wait()
      self.condition.notify()

      print("{}:切,還這麼吊...".format(self.name))
      self.condition.wait()
      self.condition.notify()


class Girl(threading.Thread):
  def __init__(self,condition):
    super().__init__(name=name)
    self.condition = condition

  def run(self):
    with self.condition:
      print("{}:哼,想泡老孃不成?".format(self.name))
      self.condition.notify()
      self.condition.wait()

      print("{}:滾蛋,門都沒有!".format(self.name))
      self.condition.notify()
      self.condition.wait()

      print("{}:關你鳥事!".format(self.name))
      self.condition.notify()
      self.condition.wait()


if __name__ == '__main__':
  condition = threading.Condition()
  boy_thread = Boy('男',condition)
  girl_thread = Girl('女',condition)

  boy_thread.start()
  girl_thread.start()

Condition的底層實現了__enter__和 __exit__協議.所以可以使用with上下文管理器

由Condition的__init__方法可知,它的底層也是維護了一個RLock鎖

 def __enter__(self):
    return self._lock.__enter__()
  def __exit__(self,*args):
    return self._lock.__exit__(*args)
 def __exit__(self,t,v,tb):
    self.release()
def release(self):
    """Release a lock,decrementing the recursion level.

    If after the decrement it is zero,reset the lock to unlocked (not owned
    by any thread),and if any other threads are blocked waiting for the
    lock to become unlocked,allow exactly one of them to proceed. If after
    the decrement the recursion level is still nonzero,the lock remains
    locked and owned by the calling thread.

    Only call this method when the calling thread owns the lock. A
    RuntimeError is raised if this method is called when the lock is
    unlocked.

    There is no return value.

    """
    if self._owner != get_ident():
      raise RuntimeError("cannot release un-acquired lock")
    self._count = count = self._count - 1
    if not count:
      self._owner = None
      self._block.release()

至於wait/notify是如何操作的,還是有點懵.....

wait()方法原始碼中這樣三行程式碼

waiter = _allocate_lock() #從底層獲取了一把鎖,並非Lock鎖
waiter.acquire()
self._waiters.append(waiter) # 然後將這個鎖加入到_waiters(deque)中
saved_state = self._release_save() # 這是釋放__enter__時的那把鎖???

notify()方法原始碼

all_waiters = self._waiters  
waiters_to_notify = _deque(_islice(all_waiters,n))# 從_waiters中取出n個
if not waiters_to_notify:  # 如果是None,結束
   return
for waiter in waiters_to_notify: # 迴圈release
   waiter.release()
   try:
     all_waiters.remove(waiter) #從_waiters中移除
   except ValueError:
     pass

大體意思: wait先從底層建立鎖,acquire,放到一個deque中,然後釋放掉with鎖,notify時,從deque取拿出鎖,release

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