您好,登錄后才能下訂單哦!
這篇文章主要介紹“Python Thread虛假喚醒概念與防范代碼分析”,在日常操作中,相信很多人在Python Thread虛假喚醒概念與防范代碼分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Python Thread虛假喚醒概念與防范代碼分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
虛假喚醒是一種現象,它只會出現在多線程環境中,指的是在多線程環境下,多個線程等待在同一個條件上,等到條件滿足時,所有等待的線程都被喚醒,但由于多個線程執行的順序不同,后面競爭到鎖的線程在獲得時間片時條件已經不再滿足,線程應該繼續睡眠但是卻繼續往下運行的一種現象。
上面是比較書面化的定義,我們用人能聽懂的話來介紹一下虛假喚醒。
多線程環境的編程中,我們經常遇到讓多個線程等待在一個條件上,等到這個條件成立的時候我們再去喚醒這些線程,讓它們接著往下執行代碼的場景。假如某一時刻條件成立,所有的線程都被喚醒了,然后去競爭鎖,因為同一時刻只會有一個線程能拿到鎖,其他的線程都會阻塞到鎖上無法往下執行,等到成功爭搶到鎖的線程消費完條件,釋放了鎖,后面的線程繼續運行,拿到鎖時這個條件很可能已經不滿足了,這個時候線程應該繼續在這個條件上阻塞下去,而不應該繼續執行,如果繼續執行了,就說發生了虛假喚醒。
import threading from threading import Condition class Data: def __init__(self, cond, num): self.num = num self.cond = cond def add(self): self.cond: Condition = self.cond self.cond.acquire() if self.num > 0: self.cond.wait() self.num += 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() def decr(self): self.cond: Condition = self.cond self.cond.acquire() if self.num == 0: self.cond.wait() self.num -= 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() if __name__ == '__main__': cond = Condition() num = 0 data = Data(cond, 0) thread_add = threading.Thread(name="A", target=data.add) thread_decr = threading.Thread(name="B", target=data.decr) thread_add.start() thread_decr.start()
import threading from threading import Condition class Data: def __init__(self, cond, num): self.num = num self.cond = cond def add(self): self.cond: Condition = self.cond self.cond.acquire() if self.num > 0: self.cond.wait() self.num += 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() def decr(self): self.cond: Condition = self.cond self.cond.acquire() if self.num == 0: self.cond.wait() self.num -= 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() if __name__ == '__main__': cond = Condition() num = 0 data = Data(cond, 0) thread_add = threading.Thread(name="A", target=data.add) thread_decr = threading.Thread(name="B", target=data.decr) thread_add2 = threading.Thread(name="C", target=data.add) thread_decr2 = threading.Thread(name="D", target=data.decr) thread_add.start() thread_decr.start() thread_add2.start() thread_decr2.start()
還沒有出現問題!!!
import threading from threading import Condition class Data: def __init__(self, cond, num): self.num = num self.cond = cond def add(self): self.cond: Condition = self.cond self.cond.acquire() if self.num > 0: self.cond.wait() self.num += 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() def decr(self): self.cond: Condition = self.cond self.cond.acquire() if self.num == 0: self.cond.wait() self.num -= 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() if __name__ == '__main__': cond = Condition() num = 0 data = Data(cond, 0) for i in range(10): thread_add = threading.Thread(name="A", target=data.add) thread_add.start() for i in range(10): thread_decr = threading.Thread(name="B", target=data.decr) thread_decr.start()
這時就出現了問題!!!
防止虛假喚醒:
import threading from threading import Condition class Data: def __init__(self, cond, num): self.num = num self.cond = cond def add(self): self.cond: Condition = self.cond self.cond.acquire() # 這里采用了while進行判斷,防止虛假喚醒 while self.num > 0: self.cond.wait() self.num += 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() def decr(self): self.cond: Condition = self.cond self.cond.acquire() # 這里采用了while進行判斷,防止虛假喚醒 while self.num == 0: self.cond.wait() self.num -= 1 print(threading.current_thread().getName(), self.num) self.cond.notifyAll() self.cond.release() if __name__ == '__main__': cond = Condition() num = 0 data = Data(cond, 0) for i in range(10): thread_add = threading.Thread(name="A", target=data.add) thread_add.start() for i in range(10): thread_decr = threading.Thread(name="B", target=data.decr) thread_decr.start()
這個例子與上面的代碼幾乎沒有差別,只是把if判斷換成了while判斷,所以每次蕭炎和唐三醒過來之后都會再判斷一下有沒有蘋果(喚醒自己的條件是否滿足),如果不滿足,就會繼續睡下去,不會接著往下運行,從而避免了虛假喚醒。
到此,關于“Python Thread虛假喚醒概念與防范代碼分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。