threadモジュール—Pythonマルチスレッドプログラミング

11109 ワード

Threadモジュール
*注意:実際の使用ではthreadを使用したマルチスレッドプログラミングは推奨されません.このドキュメントでは、マルチスレッドの学習(または熟知)にのみ使用します.
Threadモジュールは、派生スレッドに加えて、ロックオブジェクト(lock object、原語ロック、反発ロック、反発、バイナリ信号量とも呼ばれる)と呼ばれる基本的な同期データ構造を提供する.
一般的なスレッド関数およびLockTypeオブジェクトのロック方法:
関数/メソッド
説明
threadモジュールの関数
 
start_new_thread(function, args, kwargs=None)
新しいスレッドを派生し、与えられたargsとオプションのkwargsを使用してfunctionを実行します.
allocate_lock()
ロックタイプロックオブジェクトの割り当て
exit()
スレッド終了命令
ロックタイプオブジェクトロック方法
 
acquire(wait=None)
ロックオブジェクトの取得を試みる
locked()
ロックされたオブジェクトを取得した場合はTrueを返し、そうでなければFlaseを返します.
release()
リリースロック
 
threadモジュールを使用する簡単な例です.コードは次のとおりです(mtsleepA.py).
 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」を表示して終了し、loop 0()とloop 1()の2つのスレッドが直接終了するためです.
 
スレッドとロックの簡単な例を使用すると、コードは次のようになります(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ループ)の説明:
まずthreadを使用してロックリストを作成します.allocate_lock()関数はロックオブジェクトを得る;
さらにacquire()法により各ロックを取得する(ロックを取得する効果は「ロックをロックする」に相当する).
ロックをロックした後、ロックリストlocksに追加します.
なぜロックされたループでスレッドを起動しないのですか?
第一に、すべてのスレッドが最後に同時に完了するようにスレッドを同期したい.
第二に、ロックを取得するには、スレッドの実行が速すぎることを避けるために、ロックを取得する前にスレッドの実行が終了する時間がかかります.