<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Python中執行緒有兩種方式:函數或者用類來包裝執行緒物件。threading模組中包含了豐富的多執行緒支援功能:
通過Thread類來處理執行緒,類中提供的一些方法:
通過Thread直接構造執行緒,然後通過start方法啟動執行緒:
threading.Thread(group=None, target=None, name=None, args=(), kwargs=None, *,daemon=None)
各引數說明:
def simpleRoutine(name, delay): print(f"routine {name} starting...") time.sleep(delay) print(f"routine {name} finished") if __name__ == '__main__': thrOne = threading.Thread(target=simpleRoutine, args=("First", 1)) thrTwo = threading.Thread(target=simpleRoutine, args=("Two", 2)) thrOne.start() thrTwo.start() thrOne.join() thrTwo.join()
直接繼承Thread,建立一個新的子類(主要實現run方法):
class SimpleThread (threading.Thread): def __init__(self, name, delay): # threading.Thread.__init__(self) super().__init__() self.name = name self.delay = delay def run(self): print(f"thread {self.name} starting...") time.sleep(self.delay) print(f"thread {self.name} finished") if __name__ == '__main__': thrOne = SimpleThread("First", 2) thrTwo = SimpleThread("Second", 2) thrOne.start() thrTwo.start() thrOne.join() thrTwo.join()
當多個執行緒同時修改同一條資料時可能會出現髒資料;所以,就需要執行緒鎖,即同一時刻只允許一個執行緒執行操作。
threading提供了Lock和RLock(可重入鎖)兩個類,它們都提供瞭如下兩個方法來加鎖和釋放鎖:
兩種使用鎖的方式:
gCount = 0 def PlusOne(locker): global gCount with locker: gCount += 1、 def MinusOne(locker): global gCount if locker.acquire(): gCount -= 1 locker.release()
Condition物件內部維護了一個鎖(構造時可傳遞一個Lock/RLock物件,否則內部會自行建立一個RLock)和一個waiting池:
Condition物件:
__init__(self,lock=None)
:Condition類總是與一個鎖相關聯(若不指定lock引數,會自動建立一個與之繫結的RLock物件);
acquire(timeout)
:呼叫關聯鎖的acquire()方法;
release()
:呼叫關聯鎖的release()方法
wait(timeout)
:執行緒掛起,直到收到一個notify通知或超時才會被喚醒;必須在已獲得鎖的前提下呼叫;
notify(n=1)
:喚醒waiting池中的n個正在等待的執行緒並通知它:
notify_all()
:通知所有執行緒。
class Producer(threading.Thread): def __init__(self, cond, storage): threading.Thread.__init__(self) self.cond = cond self.storage = storage def run(self): label = 1 while True: with self.cond: if len(self.storage) < 10: self.storage.append(label) print(f"<- Produce {label} product") label += 1 self.cond.notify(2) else: print(f"<- storage full: Has Produced {label - 1} product") self.cond.notify_all() self.cond.wait() time.sleep(0.4) class Consumer(threading.Thread): def __init__(self, name, cond, storage): threading.Thread.__init__(self) self.name = name self.cond = cond self.storage = storage def run(self): while True: if self.cond.acquire(): if len(self.storage) > 1: pro = self.storage.pop(0) print(f"-> {self.name} consumed {pro}") self.cond.notify() else: print(f"-> {self.name} storage empty: no product to consume") self.cond.wait() self.cond.release() time.sleep(1)
號誌物件內部維護一個計數器:
acquire(blocking=True,timeout=None)
時減1,當計數為0就阻塞請求的執行緒;release()
時加1,當計數大於0恢復被阻塞的執行緒;threading中有Semaphore和BoundedSemaphore兩個號誌;BoundedSemaphore限制了release的次數,任何時候計數器的值,都不不能大於初始值(release時會檢測計數器的值,若大於等於初始值,則丟擲ValueError異常)。
通過Semaphore維護生產(release一個)、消費(acquire一個)量:
# products = threading.Semaphore(0) def produceOne(label, sem: threading.Semaphore): sem.release() print(f"{label} produce one") def consumeOne(label, sem: threading.Semaphore): sem.acquire() print(f"{label} consume one")
通過BoundedSemaphore來控制並行數量(最多有Semaphore初始值數量的執行緒並行):
# runner = threading.BoundedSemaphore(3) def runBound(name, sem: threading.BoundedSemaphore): with sem: print(f"{name} is running") time.sleep(1) print(f"{name} finished")
事件物件內部有個標誌欄位,用於執行緒等待事件的發生:
多執行緒等待事件發生,然後開始執行:
def waiters(name, evt: threading.Event): evt.wait() print(f"{name} is running") time.sleep(1) print(f"{name} finished") def starting(evt: threading.Event): evt.set() print("event is set")
屏障用於設定等待執行緒數量,當數量達到指定值時,開始執行:
threading.Barrier(parties, action=None, timeout=None)
屏障屬性與方法:
def waitBarrier(name, barr: threading.Barrier): print(f"{name} waiting for open") try: barr.wait() print(f"{name} running") time.sleep(5) except threading.BrokenBarrierError: print(f"{name} exception") print(f"{name} finished")
GIL(Global Interpreter Lock,全域性直譯器鎖);cpython中,某個執行緒想要執行,必須先拿到GIL(可以把GIL看作是“通行證”)。每次釋放GIL鎖,執行緒都要進行鎖競爭,切換執行緒,會消耗資源。
由於GIL鎖的存在,python裡一個程序永遠只能同時執行一個執行緒(拿到GIL的執行緒),這就是為什麼在多核CPU上,python的多執行緒效率並不高:
python在使用多執行緒的時候,呼叫的是c語言的原生執行緒:
到此這篇關於Python多執行緒與同步機制淺析的文章就介紹到這了,更多相關Python多執行緒內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45