Python的线程/进程间通讯对象分析
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
Python提供了一系列的對(duì)象支持線程/進(jìn)程間的通訊:
除了Lock,Rlock外,進(jìn)程的相關(guān)對(duì)象只是線程相關(guān)對(duì)象的clone,而且進(jìn)程的Lock,RLock也是與線程Lock,RLock相對(duì)應(yīng)的對(duì)象。在這里我們只分析線程的這幾種對(duì)象。
一般使用范圍:
Lock用于對(duì)互斥操作(單一資源,全局變量)
RLock與Lock類(lèi)似,區(qū)別僅在與RLock在同一個(gè)線程可以多次獲取
Semaphone/BounderSemaphone用于對(duì)多個(gè)資源的申請(qǐng)使用, 如果BounderSemaphone(1)則==Lock()
Condition用于在等待某種事情發(fā)生
Event實(shí)際上是對(duì)Condition的一種操作簡(jiǎn)化包裝,也更符合事件驅(qū)動(dòng)的概念。
這幾種對(duì)象大概使用上面這些對(duì)象所要付出的開(kāi)銷(xiāo)是不同的,我們從其原理來(lái)進(jìn)行分析。
from time import sleep
from threading import Thread, Lock
Lock的使用方法參考上面的代碼,而RLock是跟Lock的區(qū)別是如果在本線程已經(jīng)acquire,則可以多次acquire,不同線程下則跟Lock是一致的;我們來(lái)看一下RLock的實(shí)現(xiàn):
class _RLock:def __init__(self):self._block = _allocate_lock()self._owner = Noneself._count = 0def acquire(self, blocking=True, timeout=-1):me = get_ident() # 獲取當(dāng)前thread的identityif self._owner == me: # 鎖的所有者是自己self._count += 1return 1rc = self._block.acquire(blocking, timeout) #獲取鎖if rc:self._owner = meself._count = 1return rc從上面的代碼可以看出,RLock實(shí)際上是使用了Lock,只是在acquire時(shí)判斷了是否是本線程,如果是,則記錄lock次數(shù)不做阻塞返回。
而Condition在調(diào)用wait時(shí)則新生成了一個(gè)Lock,并acquire了兩次已達(dá)到阻塞的目的,而。
class Condition:def __init__(self, lock=None):.....self._waiters = _deque() # 初始化waiter Lock 隊(duì)列def wait(self, timeout=None):if not self._is_owned(): # 必須要先獲取鎖raise RuntimeError("cannot wait on un-acquired lock")waiter = _allocate_lock()waiter.acquire()self._waiters.append(waiter) #將waiter Lock加入waiter隊(duì)列.....waiter.acquire()def _is_owned(self):# Return True if lock is owned by current_thread.# This method is called only if _lock doesn't have _is_owned().if self._lock.acquire(0):self._lock.release() # 在wait,notify時(shí)會(huì)釋放互斥鎖return Falseelse:return Truedef notify(self, n=1):if not self._is_owned(): # 必須要先獲取鎖raise RuntimeError("cannot notify on un-acquired lock")all_waiters = self._waiterswaiters_to_notify = _deque(_islice(all_waiters, n))if not waiters_to_notify:returnfor waiter in waiters_to_notify:waiter.release() #根據(jù)通知數(shù)量依次釋放Lock只是一個(gè)單純的互斥體,而Condition則可在某種條件發(fā)生后主動(dòng)通知正在等待某種條件的線程。
from threading import Thread, Lock, Conditionclass MyWaitThread(Thread):def __init__(self, name, cond):super(MyWaitThread, self).__init__(name=name)# self.name = nameself.cond = conddef run(self):with self.cond:print('I am waiting something happen!')self.cond.wait()print('wait end!')class MyNotifyThread(Thread):def __init__(self, name, cond):super(MyNotifyThread, self).__init__(name=name)# self.name = nameself.cond = conddef run(self):with self.cond:print('I am notifying all the wait thread.')self.cond.notify_all()print('notify end.')if __name__ == '__main__':cond = Condition()mt1 = MyWaitThread('t1', cond)mt2 = MyWaitThread('t2', cond)mt3 = MyNotifyThread('t3', cond)mt1.start(); mt2.start(); mt3.start()mt1.join(); mt2.join();mt3.join()print('main thread end!')Semaphone使用Condition的wait,notify來(lái)實(shí)現(xiàn),但是卻可以看成一個(gè)可以在不同線程中同時(shí)獲取N次的鎖。
轉(zhuǎn)載于:https://my.oschina.net/caoxinyu0205/blog/741819
總結(jié)
以上是生活随笔為你收集整理的Python的线程/进程间通讯对象分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 为什么忘记commit也会造成selec
- 下一篇: python 学习笔记day03-pyt