ホームページ >バックエンド開発 >Python チュートリアル >Pythonスレッドの実践
"""" Python でスレッドを使用するには、スレッド オブジェクトをラップする関数またはクラスの 2 つの方法があります。
1. 機能: thread モジュールで start_new_thread() 関数を呼び出して、新しいスレッドを生成します。スレッドは、スレッドが自然に終了するのを待つか、スレッド関数で thread.exit() メソッドまたは thread.exit_thread() メソッドを呼び出すことによって終了できます。
インポート時間
インポートスレッド
def timer(no,interval):
cnt=0
while cnt print 'thread(%d)'%(cnt)
time.sleep(interval)
cnt= cnt+1
def test():
thread.start_new_thread(timer,(1,1))
thread.start_new_thread(timer,(2,2))
if __name__=='__main__':
print ' thread starting'
test()
time.sleep(20)
thread.exit_thread()
print 'exit...'
2. スレッド オブジェクトをラップする threading.Thread のサブクラス、
threading.Thread クラスを作成します。 :
1、独自のスレッドクラスの __init__ で threading.Thread.__init__(self, name = threadname) を呼び出します
Threadname はスレッドの名前です
2、run()、通常は書き換えて書き込む必要がありますコードは必要な機能を実装します。
3, getName(), スレッドオブジェクト名を取得します
4, setName(), スレッドオブジェクト名を設定します
5, start(), スレッドを開始します
6, jion([timeout]), wait別のスレッドを終了してから再度実行します。
7、setDaemon(bool)、サブスレッドがメインスレッドで終了するかどうかを設定し、start() の前に呼び出す必要があります。デフォルトは False です。
8、 isDaemon() は、スレッドがメインスレッドで終了するかどうかを決定します。
9、isAlive()、スレッドが実行されているかどうかを確認します。
インポートスレッド
インポート時間
クラスタイマー(threading.Thread):
def __init__(self,num,interval):
threading.Thread.__init__(self)
self.thread_num=num
self.interval=interval
self .thread_stop=False
def run(self):
while not self.thread_stop:
print 'thread object (%d), time %sn' %(self.thread_num,time.ctime())
time.sleep( self.interval)
def stop(self):
self.thread_stop=True
def test():
thread1=timer(1,1)
thread2=timer(2,2)
thread1.start()
thread2.start()
time.sleep(10)
thread1.stop()
thread2.stop()
return
if __name__=='__main__':
test()
"""
"""
質問その理由は、同じリソースへの複数のスレッドのアクセスが制御されていないため、データが損傷し、スレッド操作の結果が予測不能になるためです。この現象は「スレッドアンセーフ」と呼ばれます。
インポートスレッド
インポート時間
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg='I am '+ self.getName ()+'@'+str(i)
() ':
test()
上記の例は、マルチスレッドプログラミングの最も一般的な問題につながります:データ共有。ある共有データを複数のスレッドで変更する場合、同期制御が必要となります。
スレッド同期により、複数のスレッドが競合するリソースに安全にアクセスできるようになります。最も簡単な同期メカニズムは、ミューテックス ロックを導入することです。ミューテックスは、ロック/ロック解除という状態をリソースに導入します。スレッドが共有データを変更したい場合は、まずそのリソースをロックする必要があり、その時点でリソースのステータスは「ロック」されており、スレッドがリソースを解放してリソースのステータスを「」に変更するまで、他のスレッドはそれを変更できません。ロックが解除されました」と表示された場合、他のスレッドはリソースを再度ロックできます。ミューテックス ロックは、一度に 1 つのスレッドだけが書き込み操作を実行することを保証するため、マルチスレッド状況でのデータの正確性が保証されます。このうち、lockメソッドacquireはタイムアウト期間のパラメータtimeoutをオプションで持つことができます。タイムアウトが設定されている場合、戻り値を使用してタイムアウト後にロックが取得されたかどうかを判断できるため、他の処理を実行できます
Lock クラスはスレッド モジュールで定義されます
インポート スレッド
インポート時間
クラス MyThread(threading.Thread ):
def run(self):
グローバル数値
time.sleep(1)
if mutex.acquire(): num=num+1
print self.name+' num を '+str(num)+'n' に設定
mutex.release()
num =0
mutex=threading.Lock()
def test():
for i in range(5):
t=MyThread()
t.start()
if __name__=='__main__':
テスト()
"""
"""より単純なデッドロック状況は、スレッドが同じリソースを要求することを「反復」する場合であり、これにより直接デッドロックが発生します。
インポート スレッド
インポート時間
class MyThread(threading.Thread) :
def run(self):
‐ num = num + 1
name+' set num to '+str(num) G Mutex に MSG を出力.acquire ()
mutex.release ()
mutex.release ()
num = 0
mutex = Threading.lock ()
Range (5) の I :
T = MyThread()
t.start()
if __name__ == '__main__':
test()
同じスレッド内の同じリソースに対する複数のリクエストをサポートするために、Python は「再入可能ロック」threading.RLock を提供します。 RLock は内部でロックとカウンター変数を維持するため、リソースが複数回必要になる可能性があるため、カウンターは取得回数を記録します。スレッドのすべての取得が解放されるまで、他のスレッドはリソースを取得できます。上記の例では、Lock の代わりに RLock が使用されている場合、デッドロックは発生しません。
インポート スレッド
インポート時間
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1 )
if mutex。 use using use using use using using using through through ‐ ‐ off ‐ ‐ ‐ ‐ ‐ ‐ ()
num = 0
mutex = threading.RLock()
defテスト():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
"""
"""
Python マルチスレッド プログラミング (5) ): 条件変数の同期
Mutex ロックは、Python によって提供される最も単純なスレッド同期メカニズムであり、複雑なスレッド同期の問題の解決策を提供します。 Condition は条件変数と呼ばれ、Lock と同様の取得メソッドと解放メソッドを提供するだけでなく、待機メソッドと通知メソッドも提供します。スレッドは最初に条件変数を取得し、次にいくつかの条件を決定します。条件が満たされない場合は待機し、条件が満たされた場合は条件を変更する処理を実行し、通知を受け取った後に待機状態にある他のスレッドに条件を再判断します。このプロセスは、複雑な同期問題を解決するために継続的に繰り返されます。
Condition オブジェクトはロック (Lock/RLock) と待機プールを維持すると考えることができます。スレッドは、取得によって Condition オブジェクトを取得します。wait メソッドが呼び出されると、スレッドは Condition 内のロックを解放し、同時に待機プールに記録されます。通知メソッドが呼び出されると、Condition オブジェクトは待機プールからスレッドを選択し、取得メソッドを呼び出してロックの取得を試みるよう通知します。
Condition オブジェクトのコンストラクターは、Lock/RLock オブジェクトをパラメーターとして受け入れることができます。指定されていない場合、Condition オブジェクトは内部で RLock を作成します。
Condition オブジェクトは、notify メソッドに加えて、待機プール内のすべてのスレッドに内部ロックの取得を試みるよう通知できる、notifyAll メソッドも提供します。上記の仕組みにより、待機状態のスレッドはnotifyメソッドでしか起動できないため、スレッドが永久に沈黙することを防ぐのがnotifyAllの機能です。
条件変数の同期を示す古典的な問題は、生産者と消費者の問題です。市場を通じて製品と対話する生産者のグループ (Producer) と消費者のグループ (Consumer) があると仮定します。生産者の「戦略」は、市場に製品が 1,000 個未満残っている場合は 100 個の製品を生産し、市場に投入することですが、消費者の「戦略」は、市場に製品が 100 個以上残っている場合は 100 個の製品を生産することです。 . 3つの製品を消費します。プロデューサーとコンシューマーの問題を解決するために Condition を使用するコードは次のとおりです。
インポート スレッド
インポート時間
classProducer(threading.Thread):
def run(self):
global count
while True:
if con .acquire() :
if count & gt; 1000:
con.wait ()
else:
Count = Count+100
Print Self.name+'Produce 100, Count ='+Str (Count)
TIME。 (1)
class Customer(threading.Thread):
def run(self):
global count
while True:
if con.acquire():
if count>100:
count=count-100
print self .name+ 'consume 100, count='+str(count)
else:
con.wait()
con.release() time.sleep(1)
count=500
con=threading.Condition()
def test():
for i in range(5):
p=Producer()
p.start()
c=Customer()
c.start()
print i
if __name__==' __main__ ':
test()
Python のデフォルトのグローバル変数は関数内で読み取ることができますが、書き込むことはできませんが、
con でのみ読み取り可能なため、グローバル """ を導入する必要はありません