*注:在實際使用過程當中不建議使用 thread 進行多線程編程,本文檔只爲學習(或熟悉)多線程使用。編程
Thread 模塊除了派生線程外,還提供了基本的同步數據結構,稱爲鎖對象(lock object,也叫原語鎖、互斥鎖、互斥和二進制信號量)。數據結構
經常使用線程函數以及 LockType 鎖對象的方法:多線程
函數/方法 | 描述 |
---|---|
thread 模塊的函數 | |
start_new_thread(function, args, kwargs=None) | 派生一個新的線程,使用給定的 args 和可選的 kwargs 來執行 function |
allocate_lock() | 分配 LockType 鎖對象 |
exit() | 給線程退出指令 |
LockType 鎖對象方法 | |
acquire(wait=None) | 嘗試獲取鎖對象 |
locked() | 若是獲取了鎖對象則返回True,不然返回 Flase |
release() | 釋放鎖 |
使用 thread 模塊的簡單例子,代碼以下(mtsleepA.py):app
1 import thread 2 from time import sleep, ctime 3 4 def loop0(): 5 print 'start loop 0 at:', ctime() 6 sleep(4) 7 print 'loop 0 Done at:', ctime() 8 9 def loop1(): 10 print 'start loop 1 at:', ctime() 11 sleep(2) 12 print 'loop 1 Done at:', ctime() 13 14 def main(): 15 print 'starting at:', ctime() 16 thread.start_new_thread(loop0, ()) 17 thread.start_new_thread(loop1, ()) 18 sleep(6) 19 print 'all DONE at:', ctime() 20 21 if __name__ == '__main__': 22 main()
輸出結果:函數
1 starting at: Sun Jul 22 21:38:00 2018 2 start loop 0 at: Sun Jul 22 21:38:00 2018 3 start loop 1 at: Sun Jul 22 21:38:00 2018 4 loop 1 Done at: Sun Jul 22 21:38:02 2018 5 loop 0 Done at: Sun Jul 22 21:38:04 2018 6 all DONE at: Sun Jul 22 21:38:06 2018
在這個腳本的代碼中,增長了一個 sleep(6) 調用,爲何要這麼作呢?這是由於若是咱們沒有阻止主線程繼續執行,它將會繼續執行下一條語句,顯示「all done」而後退出,而 loop0() 和 loop1() 這兩個線程將直接終止。oop
使用線程和鎖的簡單例子,代碼以下(mtsleepB.py):學習
1 import thread 2 from time import sleep, ctime 3 4 loops = [4,2] 5 6 def loop(nloop, nsec, lock): 7 print 'start loop', nloop, 'at:', ctime() 8 sleep(nsec) 9 print 'loop', nloop, 'done at:', ctime() 10 lock.release() # 釋放鎖 11 12 def main(): 13 print 'starting at:', ctime() 14 locks = [] 15 nloops = range(len(loops)) 16 17 for i in nloops: 18 lock = thread.allocate_lock() # 分配 LockType 對象 19 lock.acquire() # 嘗試獲取鎖對象 20 locks.append(lock) 21 22 for i in nloops: 23 thread.start_new_thread(loop, (i, loops[i], locks[i])) # 派生新線程 24 25 for i in nloops: 26 # 等待全部鎖釋放後退出循環繼續後面操做 27 while locks[i].locked(): # 當獲取了鎖的時候爲 True,全部的鎖都釋放後爲 Flase 28 pass 29 30 print 'all DONE at:', ctime() 31 32 if __name__ == '__main__': 33 main()
輸出結果爲:
1 starting at: Sun Jul 22 22:25:45 2018 2 start loop 1 at:start loop Sun Jul 22 22:25:45 2018 3 0 at: Sun Jul 22 22:25:45 2018 4 loop 1 done at: Sun Jul 22 22:25:47 2018 5 loop 0 done at: Sun Jul 22 22:25:49 2018 6 all DONE at: Sun Jul 22 22:25:49 2018
main() 函數中鎖相關的主要流程(第一個 for 循環)解釋:ui
首先建立一個鎖列表,經過使用 thread.allocate_lock() 函數獲得鎖對象;spa
再經過 acquire() 方法取得每一個鎖(取得鎖的效果至關於「把鎖鎖上」);線程
把鎖鎖上後將它添加到鎖列表 locks 中;
爲何不在上鎖的循環中啓動線程呢?
第一,想要同步線程,讓全部的線程最後同時都完成;