標籤:針對 pre 操作 range 結束 原因 for 執行 ctime
一.關於Python多線程
Python解譯器中可以同時運行多個線程,但是再任意時刻只能有一個線程在解譯器運行。
Python虛擬機器的訪問是由全域解鎖器(GIL)控制的,由GIL保證同時只有一個線程的運行。
執行方式如下:
1.設定GIL
2.切換進一個進程執行
3.執行下面操作中的一個
a.運行指定數量的位元組碼(作業系統中是由時鐘控制的)
b.線程主動出讓控制權
4.把線程設定為睡眠狀態,即切換出線程
5.解鎖GIL
6.重複以上步驟
注意:1.調用外部代碼時(C/C++擴充的內建函數),GIL保持鎖定,因為外部代碼沒有Python位元組碼.
2.I/O密集型的Python程式要比計算密集型的程式更好的利用多線程。
二.關於thead模組的多線程:
樣本1,當沒有使用多線程時:
1 from time import sleep, ctime 2 3 def loop(): 4 print(‘start loop0 at:‘, ctime()) 5 sleep(4) 6 print(‘loop 0 done at:‘, ctime()) 7 8 def loop1(): 9 print(‘start loop1 at:‘, ctime())10 sleep(2)11 print(‘loop1 done at:‘, ctime())12 13 def main():14 print(‘starting at:‘, ctime())15 loop()16 loop1()17 print(‘loop1 done at:‘, ctime())18 19 if __name__ == ‘__main__‘:20 main()
輸出結果為:
starting at: Mon Dec 19 22:17:42 2016
start loop0 at: Mon Dec 19 22:17:42 2016
loop 0 done at: Mon Dec 19 22:17:46 2016
start loop1 at: Mon Dec 19 22:17:46 2016
loop1 done at: Mon Dec 19 22:17:48 2016
loop1 done at: Mon Dec 19 22:17:48 2016
從結果可以看出loop0和loop按照順序執行,耗時一共6s
thread模組的核心函數是:start_new_thread()
用法:_thread.start_new_thread(func, *arg, **kwargs)
樣本2,當使用多線程時候:
1 import _thread 2 from time import sleep, ctime 3 4 def loop0(): 5 print(‘start loop0 at:‘, ctime()) 6 sleep(4) 7 print(‘loop0 done at:‘, ctime()) 8 9 def loop1():10 print(‘start loop1 at:‘, ctime())11 sleep(2)12 print(‘loop1 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 22 if __name__ == ‘__main__‘:23 main()
結果為:
starting at: Mon Dec 19 22:27:57 2016
start loop0 at: Mon Dec 19 22:27:57 2016
start loop1 at: Mon Dec 19 22:27:57 2016
loop1 done at: Mon Dec 19 22:27:59 2016
loop0 done at: Mon Dec 19 22:28:01 2016
all done at: Mon Dec 19 22:28:03 2016
從結果可以看出,1.結果不是按照順序輸出的,loop0後結束
2.loop0和loop1的已耗用時間一共是4s,比沒有使用多線程快了2s
3.sleep(6)是針對主線程的,預計loop0和loop1會在6s前執行完畢。
如果我們把主線程的執行時間設定為3s,那麼結果就有意思了
starting at: Mon Dec 19 22:33:01 2016
start loop0 at: Mon Dec 19 22:33:01 2016
start loop1 at: Mon Dec 19 22:33:01 2016
loop1 done at: Mon Dec 19 22:33:03 2016
all done at: Mon Dec 19 22:33:04 2016
從這個結果哦可以看出,loop0沒有執行完畢就被迫退出!!!原因是主線程的切出時間為3s,3s
過後主線程繼續執行,loop0即使沒運行完畢,被迫退出!!
從這裡也可以看出,對主線程執行sleep()來達到同步的目的不可靠,所以引入鎖的概念。
樣本3,使用鎖的多線程:
1 import _thread 2 from time import sleep, ctime 3 4 loops = [4, 2] 5 6 7 def loop(nloop, nsec, lock): 8 print(‘start loop‘, nloop, ‘at:‘, ctime()) 9 sleep(nsec)10 print(‘loop‘, nloop, ‘done at‘, ctime())11 lock.release() #釋放鎖12 13 14 def main():15 print(‘starting at:‘, ctime())16 locks = []17 18 for i in range(len(loops)):19 lock = _thread.allocate_lock()20 lock.acquire() #鎖上鎖21 locks.append(lock) #儲存鎖22 23 for i in range(len(loops)):24 _thread.start_new_thread(loop, (i, loops[i], locks[i]))25 26 for i in range(len(loops)):27 while locks[i].locked(): pass #使用忙等待暫停主線程,直到所有的鎖都被釋放繼續主線程,28 29 print(‘all done at‘, ctime())30 31 if __name__ == ‘__main__‘:32 main()
結果:
starting at: Mon Dec 19 22:52:02 2016
start loop 0 at: Mon Dec 19 22:52:02 2016
start loop 1 at: Mon Dec 19 22:52:02 2016
loop 1 done at Mon Dec 19 22:52:04 2016
loop 0 done at Mon Dec 19 22:52:06 2016
all done at Mon Dec 19 22:52:06 2016
從結果可以看出,使用所的多線程,已耗用時間為4s,而且不用人為的設定主線程切出時間。
參考資料:Python核心編程.第四章.Wesley Chun著
【[email protected]】thread模組