Python的threading模塊松散地基于Java的threading模塊。但現在線程沒有優先級,沒有線程組,不能被銷毀、停止、暫停、開始和打斷。 Java Thread類的靜態方法,被移植成了模塊方法。
main thread: 運行python程序的線程
daemon thread 守護線程,如果守護線程之外的線程都結束了。守護線程也會結束,并強行終止整個程序。不要在守護進程中進行資源相關操作。會導致資源不能正確的釋放。在非守護進程中使用Event。
Thread 類
(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)group: 為以后的ThreadGroup類預留target: 被執行的對象,由run()方法執行args: target對象使用的參數daemon: 是否為守護進程
start()
每個thread 對象都只能被調用1次start()
run()
如果創建Thread的子類,重寫該方法。負責執行target參數傳來的可執行對象。
join()
阻塞線程直到結束。
GIL
在CPython中,由于GIL的存在,Python每次只能執行一個線程。如果要充分利用多核機器的計算資源需要使用multiprocessing或者是concurrent.futures.ProcessPollExecutor。 但,但如果你想要很多I/O相關的并發操作,threding仍然是一個很好的選擇 。?因為系統自動實現了線程的上下文切換。
from threading import Threadimport requestsurl = 'http://www.baidu.com'urls = [url]*20threads = []for url in urls: t = Thread(target=requests.get, args=(url, )) t.start() threads.append(t)for t in threads: t.join()
鎖(Lock)對象
原始鎖(primitive lock),當它鎖住的時候,它是一種不屬于任何一個線程的同步原語(synchronization primitive)。 在Python中,他是目前可用的最底層的同步原語,由_thread模塊提供。
一個原始鎖有兩個狀態:locked 和unlocked。鎖創建時,處于unlocked狀態。 鎖由兩個基本方法:acquire()和release()。
當處于unlocked狀態時,acquire(()方法可以將狀態變為locked,并立即返回。當處于locked狀態時,acquire()會阻塞直至另一個線程調用了release()使改鎖解鎖,然后acquire()將鎖上鎖,并返回。
release()方法只能在鎖locked時別調用,并釋放鎖。否則會拋出RuntimeError錯誤。
如果有多個 acquire()在等待解鎖,則不確定哪一個哪一個會被觸發。
class threading.Lock
如果一個線程acquire了一個鎖,那么后續獲取它的線程都會被阻塞,直至鎖被釋放。任何線程都可以釋放鎖。
Lock是一個工廠函數,返回當前平臺下最高效的concrete Lock類的實例。
Lock支持上下文管理方法(context management protocol),也就是with 語句。在存在競態條件(race condition)的時候,要使用鎖。比如多線程共同操作某個數據。
新聞熱點
疑難解答