章XV、Pythonのマルチスレッド同期ロック、デッドロックやロック再帰

章XV、Pythonのマルチスレッド同期ロック、デッドロックやロック再帰

1.はじめに:

1.创建线程对象
t1 = threading.Thread(target=say,args=('tony',))
2.启动线程
t1.start()
后面又说了两个点就是join和守护线程的概念

これらは、基本的な使用のpythonのマルチスレッド化されています

説明:お互いに独立して、非干渉であり、データやリソースを共有するために使用されません、我々は同じデータを使用する複数のスレッドを持っている場合、その2つの関数の前に、それがリソースの競合を有し、ロックの問題は、関係なくはどのような言語では、これは避けられません。それでは再帰的ロックとデッドロックを使用して、同期ロックについて話します

2.ゲンロック

ロックは、通常、共有リソースへのアクセスを同期するために使用されています。あなたは、リソースへのアクセスのロックオブジェクトを取得するメソッドを取得呼び出す必要があるとき、各オブジェクトへの共有リソースを作成するロックリソースへのアクセスが終了するまで(他のスレッドが既にロックを取得した場合、現在のスレッドは、それが解放されるのを待つ必要があります)その後、ロックを解除するためにreleaseメソッドを呼び出します。

次のように適切な同期ロックの例です。

import threading
import time

num = 100

def fun_sub():
    global num
    # num -= 1
    num2 = num
    time.sleep(0.001)
    num = num2-1

if __name__ == '__main__':
    print('开始测试同步锁 at %s' % time.ctime())

    thread_list = []
    for thread in range(100):
        t = threading.Thread(target=fun_sub)
        t.start()
        thread_list.append(t)

    for t in thread_list:
        t.join()
    print('num is %d' % num)
    print('结束测试同步锁 at %s' % time.ctime())
-----------------------------------------------------
开始测试同步锁 at Sun Apr 28 09:56:45 2019
num is 91
结束测试同步锁 at Sun Apr 28 09:56:45 2019

そのような例が記載されている:スレッド100を作成し、共通リソースから各スレッドNUM変数にコード実行の終了まで、減算演算、以下の通常の状況を、実行するために、0〜100のスレッドために取得する必要があり、印刷NUM変数操作を実行する1回減少されます。

質問です:0が、結果は91を発見していません

コードの考え方を整理してみましょう

1. GILは、numこのリソースを持って、そして、変数NUM2に割り当てられる(すなわちスレッド1と仮定して)一つだけスレッドが0.001秒スリープので、この時間100 = NUM
2.この期間最初のスレッドスリープ0.001秒このスレッド、収率動作を行う他のCPUスレッドの実行に切り替えることである(図2に示すように、GILを取得し、CPUの使用権を取得することをスレッドを想定)、スレッド1とスレッド2もまた、同じNUMを得るNUM2に割り当てられた戻り、その後眠り、この場合、実際に又はNUM = 100
3.スレッド2スリープ時間だけでなく、実際には、まだそこにNUM 100は、上記動作を行う、NUM糸3を得ることを想定され得
4. CPUは後でスレッドに切り替え直し、スレッド図2、図3は、スレッド上で実行されたとき、それらはデクリメント行う、実際には、NUMまでむしろ降順よりも、実際には99です。
上述した他の残りのスレッド操作

解決法:ここでは、同じ時間だけにnum変数の背後で動作する1、スレッド操作を引き、その後、num個の変数を操作するためのスレッドを置くことができているのpythonの同期によってロックする必要があります。私たちは以下のことを実現する方法を見て。

import threading
import time

num = 100

def fun_sub():
    global num
    lock.acquire()
    print('----加锁----')
    print('现在操作共享资源的线程名字是:',t.name)
    num2 = num
    time.sleep(0.001)
    num = num2-1
    lock.release()
    print('----释放锁----')

if __name__ == '__main__':
    print('开始测试同步锁 at %s' % time.ctime())

    lock = threading.Lock() #创建一把同步锁

    thread_list = []
    for thread in range(100):
        t = threading.Thread(target=fun_sub)
        t.start()
        thread_list.append(t)

    for t in thread_list:
        t.join()
    print('num is %d' % num)
    print('结束测试同步锁 at %s' % time.ctime())
 ------------------------------------------------
 .......
----加锁----
现在操作共享资源的线程名字是: Thread-98
----释放锁----
----加锁----
现在操作共享资源的线程名字是: Thread-100
----释放锁----
num is 0
结束测试同步锁 at Sun Apr 28 12:08:27 2019

アイデア:私たちは、リソースを共有するために、一つだけスレッド操作を上記参照マイナス1ブロックの真ん中に、私たちは私たちが望む結果を得ることができるように、同期ロックを追加し、これは同期ロックの役割です。

3.デッドロック

はじめに:

この概念のデッドロックは、多くの場所、比較データにデッドロックが発生したかの簡単な概要を存在します

# 线程1拿到了(锁头2)想要往下执行需要(锁头1),
# 线程2拿到了(锁头1)想要往下执行需要(锁头2)
# 互相都拿到了彼此想要往下执行的必需条件,互相都不放手里的锁头.
# 产生了死锁问题

原因:システムがリソースの一部が使用中であると判断したので、Pythonのスレッドより多くの時間とリソースの共有は、二つのスレッドそれぞれがリソースの部分を占めると同時に、互いのリソースを待っている場合は、デッドロックになり、これらの全て外力の不在下でのスレッドは永遠に待機します。

from threading import Thread,Lock
mutex1 = Lock()
mutex2 = Lock()
import time
class MyThreada(Thread):
    def run(self):
        self.task1()
        self.task2()
    def task1(self):
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        mutex2.acquire()
        print(f'{self.name} 抢到了 锁2 ')
        mutex2.release()
        print(f'{self.name} 释放了 锁2 ')
        mutex1.release()
        print(f'{self.name} 释放了 锁1 ')

    def task2(self):
        mutex2.acquire()
        print(f'{self.name} 抢到了 锁2 ')
        time.sleep(1)
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        mutex1.release()
        print(f'{self.name} 释放了 锁1 ')
        mutex2.release()
        print(f'{self.name} 释放了 锁2 ')

for i in range(3):
    t = MyThreada()
    t.start()

だから、再帰的プログラムの導入のロック、このデッドロックを解決するために、

4.再帰的なロックRLOCK

原理:

threading.RLock:同じスレッドで同じリソースに対する複数の要求をサポートするために、Pythonは「再帰的なロック」を提供します。内部RLOCKは、カウンタは、資源が獲得繰り返しすることができます取得するように回数を記録し、ロックとカウンタ変数を維持します。すべてがリリースされるまで、リソースを取得するために他のスレッドをスレッドを買収

言っても過言ではない、コードを入れて

from threading import Thread,Lock,RLock
# mutex1 = Lock()
# mutex2 = Lock()
mutex1 = RLock()
mutex2 = mutex1

import time
class MyThreada(Thread):
    def run(self):
        self.task1()
        self.task2()
    def task1(self):
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        mutex2.acquire()
        print(f'{self.name} 抢到了 锁2 ')
        mutex2.release()
        print(f'{self.name} 释放了 锁2 ')
        mutex1.release()
        print(f'{self.name} 释放了 锁1 ')

    def task2(self):
        mutex2.acquire()
        print(f'{self.name} 抢到了 锁2 ')
        time.sleep(1)
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        mutex1.release()
        print(f'{self.name} 释放了 锁1 ')
        mutex2.release()
        print(f'{self.name} 释放了 锁2 ')


for i in range(3):
    t = MyThreada()
    t.start()

要約:

私たちは、原因と同期ロックデッドロックの数を解決するために、再帰的なロックを使用の上。私たちは、大規模なロック小さなロックがあるようRLOCKのみすべての小さな内部ロックがなくなるまで、他のスレッドがこのパブリックリソースを入力するのを待つために、理解置くことができます。

5.多額

もう一つのポイントは、すべてではないマルチスレッドのデータは、デッドロックが同期されていないが、共有リソースにアクセスする際に、ロックが存在するはずですので、我々は内部コードでロックし、に注意を払いますどこプラス、パフォーマンスへの影響を最小限に抑え、これはロジックの理解に依存しているでしょう。

おすすめ

転載: www.cnblogs.com/demiao/p/11543888.html