Pythonのマルチスレッドは、スレッドモジュールを使用します。 Threadingモジュールで使用されるメインクラスはThreadです。最初に、単純なマルチスレッドコードを記述しましょう。
# coding : uft-8
__ author__ ='Phtih0n'import threading
classMyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global n
print n
n +=1if"__main__"== __name__:
n =0
ThreadList =[]for i inrange(0,10):
t =MyThread()
ThreadList.append(t)for t in ThreadList:
t.start()for t in ThreadList:
t.join
マルチスレッドの最も一般的な小さな例。簡単に説明しますが、スレッド起動クラスとしてThreadクラスを継承するサブクラスMyThreadを作成しました。規則に従って、Threadのrunメソッドを書き直してください。このメソッドは、スレッドの開始後に自動的に呼び出されます。そこで、最初に10個のスレッドを作成し、それらをリストに追加しました。別のforループを使用して、各スレッドを開始します。 forループを使用する場合は、joinメソッドを呼び出して、すべてのスレッドの終了を待ってからメインスレッドを終了します。
このコードは単純に見えますが、実際には大きな問題を隠していますが、ここには反映されていません。私が10個のスレッドを作成し、これらの10個のスレッドを順番に呼び出したと本当に思いますか。各スレッドはnに1を追加します。実際、スレッドAがn ++を実行し、次にスレッドCがn ++を実行し、次にBスレッドはn ++を実行します。
これには「ロック」の問題が含まれます。オブジェクトを同時に操作する複数のスレッドがある場合、オブジェクトが十分に保護されていないと、プログラムの結果は予期しないものになります(たとえば、各スレッドの実行メソッドに時間を追加します)。 .sleep(1)と同時にスレッド名を出力すると、出力が乱雑になることがわかります。printステートメントの1つが文字の半分しか出力しないため、このスレッドは一時停止され、別のスレッドの実行が実行されます。結果は非常に厄介です)、この現象は「スレッドの不安定さ」と呼ばれます。
したがって、Threadingモジュールは、クラスThreading.Lock、lockを提供します。このタイプのオブジェクトを作成し、スレッド機能が実行される前にロックを「プリエンプト」し、実行が完了した後にロックを「解放」します。次に、一度に1つのスレッドのみがロックを保持するようにします。現時点では、パブリックオブジェクトを操作する場合、スレッドのセキュリティは発生しません。
したがって、コードを次のように変更しました。
# coding : uft-8
__ author__ ='Phtih0n'import threading, time
classMyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global n, lock
time.sleep(1)if lock.acquire():
print n , self.name
n +=1
lock.release()if"__main__"== __name__:
n =1
ThreadList =[]
lock = threading.Lock()for i inrange(1,200):
t =MyThread()
ThreadList.append(t)for t in ThreadList:
t.start()for t in ThreadList:
t.join()
最終的な実行結果:
最初にthreading.Lockクラスオブジェクトロックを作成したことがわかります。runメソッドで、lock.acquire()を使用してロックを取得しました。このとき、他のスレッドはロックを取得できなくなり、別のスレッドlock.release()によってロックが解放されるまで、「iflock.acquire()」でブロックされます。
したがって、ifステートメントの内容は完全なコードであり、他のスレッドを実行するためにその半分の実行が中断される状況はなくなりました。したがって、最終的な結果はきれいです。
Javaの場合と同様に、synchronizedキーワードを使用してメソッドを装飾します。目的は、特定のコードを中断せずに別のスレッドにジャンプすることなく、あるスレッドで実行することです。
これは、複数のスレッドが共通のオブジェクトを占有する場合です。複数のスレッドが複数の現象を呼び出したい場合、AスレッドがAロックを呼び出してAオブジェクトを占有し、BスレッドがBロックを呼び出してBオブジェクトを占有し、AスレッドがBオブジェクトを呼び出すことができず、BスレッドがAオブジェクトを呼び出すことができないため、待機していました。これにより、スレッドが「デッドロック」します。
スレッドモジュールには、リエントラントロックと呼ばれるクラスRLockもあります。ロックオブジェクトは、ロックオブジェクトとカウンターオブジェクトを内部的に維持します。カウンタオブジェクトは取得数を記録するため、リソースを複数回取得できます。最後に、すべてのRLockが解放されると、他のスレッドがリソースを取得できます。同じスレッドで、RLock.acquireを複数回呼び出すことができます。この機能を使用すると、デッドロックの問題の一部を解決できます。
デッドロックの問題は非常に複雑であり、人々は何年にもわたってそれを解決するための多くのアルゴリズムを考え出してきました。これ以上は言いませんが、ヘルプファイルを参照する必要があります。