import time
import threading
def task1(arg):while True:print("--%s--"% arg)
time.sleep(0.1)
def task2(arg):while True:print("--%s--"% arg)
time.sleep(0.1)
def main():
t1 = threading.Thread(target = task1,args =(1,))
t2 = threading.Thread(target = task2,args =(2,))
t1.start()
t2.start()if __name__ =='__main__':main()"""
--1----2----1----2----1----2----1----2----1----2--...."""
print(threading.enumerate())
マルチタスクプログラムの開発は、スレッドモジュールを使用して完了することができます。各スレッドのカプセル化をより完全にするために、スレッドモジュールを使用する場合、threading.Threadが継承されている限り、新しいサブクラスが定義されることがよくあります。 runメソッドを記述します。
# coding=utf-8import threading
import time
classMyThread(threading.Thread):
def run(self):for i inrange(3):
time.sleep(1)
# name属性は、現在のスレッドの名前を保持します
msg = self.name+':'+str(i)print(msg)if __name__ =='__main__':
t =MyThread()
t.start()
Pythonのthreading.Threadクラスには、スレッドの機能を定義するために使用されるrunメソッドがあります。このメソッドは、スレッドクラスでオーバーライドできます。独自のスレッドインスタンスを作成した後、Threadクラスのstartメソッドを使用してスレッドを開始し、スケジュールのためにpython仮想マシンに渡すことができます。スレッドが実行する機会を得ると、runメソッドを呼び出してスレッドを実行します。
from threading import Thread
import time
def work1(nums):
nums.append(44)print("----in work1---",nums)
def work2(nums):
# t1スレッドの処理が確実に行われるように、しばらく遅延します
time.sleep(1)print("----in work2---",nums)
g_nums =[11,22,33]
t1 =Thread(target=work1, args=(g_nums,))
t1.start()
t2 =Thread(target=work2, args=(g_nums,))
t2.start()
# 運用結果:
#
# - - - - in work1---[11,22,33,44]
# - - - - in work2---[11,22,33,44]
複数のスレッドが特定の共有データをほぼ同時に変更する場合、同期制御が必要です
スレッドの同期により、複数のスレッドが競合するリソースに安全にアクセスできるようになります。最も単純な同期メカニズムは、ミューテックスロックを導入することです。
ミューテックスロックは、リソースの状態を導入します:ロック/ロック解除
スレッドが共有データを変更する場合は、最初にロックします。この時点で、リソースのステータスは「ロック」されており、他のスレッドは変更できません。スレッドがリソースを解放してリソースのステータスを「非ロック」に変更するまで、他のスレッドは変更できません。リソースを再度ロックします。ミューテックスロックにより、一度に1つのスレッドのみが書き込み操作を実行するため、複数のスレッドの場合にデータの正確性が保証されます。
Lockクラスは、スレッドモジュールで定義されています。スレッドモジュールは、ロックを便利に処理できます。
# ロックを作成する
mutex = threading.Lock()
# ロック
mutex.acquire()
# 解放された
mutex.release()
import threading
import time
g_num =0
def test1(num):
global g_num
for i inrange(num):
mutex.acquire() #ロック済み
g_num +=1
mutex.release() #ロックを解除する
print("---test1---g_num=%d"%g_num)
def test2(num):
global g_num
for i inrange(num):
mutex.acquire() #ロック済み
g_num +=1
mutex.release() #ロックを解除する
print("---test2---g_num=%d"%g_num)
# ミューテックスを作成する
# デフォルトはロック解除されています
mutex = threading.Lock()
# 2つのスレッドを作成し、それぞれをgにします。_numプラス1000000回
p1 = threading.Thread(target=test1, args=(1000000,))
p1.start()
p2 = threading.Thread(target=test2, args=(1000000,))
p2.start()
# 計算が完了するのを待ちます
whilelen(threading.enumerate())!=1:
time.sleep(1)print("2つのスレッドが同じグローバル変数を操作した後の最終結果は次のとおりです。:%s"% g_num)
運用結果
- - - test1---g_num=1909909---test2---g_num=20000002スレッドが同じグローバル変数で動作した後の最終結果は次のとおりです。:2000000
最終結果を見ることができます。ミューテックスを追加した後、結果は期待どおりです。
スレッドがロックのacquire()メソッドを呼び出してロックを取得すると、ロックは「ロック」状態になります。
一度に1つのスレッドのみがロックを取得できます。この時点で別のスレッドがロックを取得しようとすると、ロックを所有するスレッドがロックのrelease()メソッドを呼び出してロックを解放するまで、スレッドは「ブロック」と呼ばれる「ブロック」状態になり、ロックは「ロック解除」状態になります。 。
スレッドスケジューラは、同期ブロッキング状態のスレッドの1つを選択してロックを取得し、スレッドを実行状態にします。
ロックの利点:
ロックのデメリット:
Recommended Posts