ホームページ > バックエンド開発 > Python チュートリアル > Python マルチスレッド プログラミング 4: デッドロックとリエントラント ロック

Python マルチスレッド プログラミング 4: デッドロックとリエントラント ロック

高洛峰
リリース: 2016-10-18 11:31:53
オリジナル
1437 人が閲覧しました

デッドロック

複数のリソースがスレッド間で共有されている場合、2 つのスレッドがそれぞれリソースの一部を占有し、同時に互いのリソースを待機すると、デッドロックが発生します。デッドロックが発生することはほとんどありませんが、デッドロックが発生すると、アプリケーションが応答を停止する可能性があります。デッドロックの例を見てみましょう:

# encoding: UTF-8
import threading
import time
  
class MyThread(threading.Thread):
    def do1(self):
        global resA, resB
        if mutexA.acquire():
             msg = self.name+' got resA'
             print msg
               
             if mutexB.acquire(1):
                 msg = self.name+' got resB'
                 print msg
                 mutexB.release()
             mutexA.release()
    def do2(self):
        global resA, resB
        if mutexB.acquire():
             msg = self.name+' got resB'
             print msg
               
             if mutexA.acquire(1):
                 msg = self.name+' got resA'
                 print msg
                 mutexA.release()
             mutexB.release()
   
      
    def run(self):
        self.do1()
        self.do2()
resA = 0
resB = 0
  
mutexA = threading.Lock()
mutexB = threading.Lock()
  
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()
ログイン後にコピー

実行結果:


Thread-1 got resA

Thread-1 got resB

Thread-1 got resB

Thread-1 got resA

Thread-2 resA

Thread-2を取得 resB

Thread-2を取得 resB

Thread-2を取得 resA

Thread-3を取得 resA

Thread-3を取得 resB

Thread-3を取得 resB

Thread-3を取得resA

Thread-5 got resA

Thread-5 got resB

Thread-5 got resB

Thread-4 got resA


この時点でプロセスは終了しました。


リエントラントロック

より単純なデッドロック状況は、スレッドが同じリソースを「反復」してリクエストする場合であり、これが直接デッドロックを引き起こします:

import threading
import time
  
class MyThread(threading.Thread):
    def run(self):
        global num
        time.sleep(1)
  
        if mutex.acquire(1): 
            num = num+1
            msg = self.name+' set num to '+str(num)
            print msg
            mutex.acquire()
            mutex.release()
            mutex.release()
num = 0
mutex = threading.Lock()
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()
ログイン後にコピー

同じスレッド内の同じリソースに対する複数のリクエストをサポートするため, Python は、threading.RLock という「再入可能なロック」を提供します。 RLock は内部でロックとカウンター変数を維持するため、リソースが複数回必要になる可能性があるため、カウンターは取得回数を記録します。スレッドのすべての取得が解放されるまで、他のスレッドはリソースを取得できます。上記の例では、Lock の代わりに RLock を使用すると、デッドロックは発生しません:

import threading
import time
  
class MyThread(threading.Thread):
    def run(self):
        global num
        time.sleep(1)
  
        if mutex.acquire(1): 
            num = num+1
            msg = self.name+' set num to '+str(num)
            print msg
            mutex.acquire()
            mutex.release()
            mutex.release()
num = 0
mutex = threading.RLock()
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()
ログイン後にコピー

実行結果:


Thread-1 set num to 1

Thread-3 set num to 2

Thread-2番号を 3 に設定します

スレッド 5 番号を 4 に設定します

スレッド 4 番号を 5 に設定します


ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート