まず、同期ロック
リソースをつかむために、スレッドの1.1複数
from threading import Thread,Lock
x = 0
def task():
global x
for i in range(200000):
x = x+1
# t1 的 x刚拿到0 保存状态 就被切了
# t2 的 x拿到0 进行+1 1
# t1 又获得运行了 x = 0 +1 1
# 这就产生了数据安全问题.
if __name__ == '__main__':
# 使用的是操作系统的原生线程.
t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(x)
共通データロック操作用の1.2
import threading
lock = threading.Lock()
lock.acquire() # 锁头
'''
公共数据的一系列操作
'''
lock.replease() # 释放锁
1.3ゲンロックリファレンス
from threading import Thread,Lock
x = 0
mutex = Lock()
def task():
global x
mutex.acquire()
for i in range(200000):
x = x+1
mutex.release()
if __name__ == '__main__':
# 使用的是操作系统的原生线程.
t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(x) #结果肯定是600000,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全
ロックは、ああ、ああはシリアル効果で、その後、私はロックしないだろう、すぐに参加した後、使用を開始、シリアル実行となりますので、
はい:間違いなく、タスクが100シリアルとなり実行されます確かに、スタートjion直後に使用し、最終的な結果は確かにあるnは0であり、それは安全であるが、問題があります
タスク内のすべてのコードは、直列に実行され、ロック、唯一の修飾部分が共有されているロック部シリアルデータ:開始直後に参加
データのセキュリティを確保するために、単一の、両方を達成することができますが、それは明らかに高い効率ロックされています。
再帰的なロックと第二に、デッドロック
いわゆるデッドロックは:実装プロセス内の2つの以上のプロセスまたはスレッドの現象をいう、外力が存在しない場合に、お互いを待っによって引き起こされるリソースの競合の結果は、彼らがそれを促進することができません。このとき、次のようにデッドロックがあると、システムがデッドロックと呼ばれる別のプロセスを待っているの過程で常にデッドロックを生成するために、デッドロック状態またはシステムであると言います
2.1デッドロックの例
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()
スレッド1グラブロック1
スレッド1グラブロック2
スレッド1リリースロック2
スレッド1リリースロック1
スレッド1グラブロック2
スレッド・ロック1 2グラブ
**:SLEEP1がロックを得たが、プロセス1sleepスレッドで、オペレーティングシステムは、他のスレッドをスケジュールしているスレッド1秒後に、ロックを取得するために別のスレッドは2を実行し、スレッドが得たときスレッド1、スレッド1を実行するようにスケジュール午前2時00分睡眠時間、CPUとをロックしますが、この時はロック1を、ロックする2必要性をリリースしてきたが、2はまだ発売されていないスレッドを取得することであった。この時点で2をロックしてから2をスレッド化に実行中の条件は、として理解することができているロック1を、得ることです:
スレッド1は、何のリリースを1つのロックを取得しません
スレッド2は、何のリリースを2ロックを取得しません
スレッド1条件付き実行は2ロックダウンされ得ることです
スレッド2がロック1の実施のための条件を降りることです
今回は、リソース消費の問題があり、プログラムはデッドロックが生じ、そこに立ち往生されていたであろう
法律を入れて解決しました:再帰的ロック
再帰的ロックは、Pythonのをサポートするために、同じリソースに対する同一スレッド複数のリクエストで、PythonはリエントラントロックRLOCKを提供します。
この内部RLOCKはロックとカウンタ変数を維持したリソースは多くの時間が必要になることができるように、カウンタは、回獲得数を記録します。すべてがリリースされるまで、リソースを取得するために他のスレッドをスレッドを取得します。もし代わりにRLOCKロックを使用して上記の例では、デッドロックが発生しません。
一つのスレッドだけを繰り返し取得できるの下で、取得には、いくつかの回をリリースする予定
デッドロックの問題を解決するために、2.2再帰的ロック
from threading import Thread,Lock,RLock
# 递归锁 在同一个线程内可以被多次acquire
# 如何释放 内部相当于维护了一个计数器 也就是说同一个线程 acquire了几次就要release几次
# 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()
# 此时程序将会正常执行结束
第三に、セマフォ
キーワード:セマフォ
代表は、マルチロックを取得することができ、複数のスレッドを持つことができながら、セマフォは、引数が整数で、引数を必要とするクラスです
いくつかのパラメータの代わりに実行することができますどのように多くの数のロックをピックアップするスレッドです
from threading import Thread,currentThread,Semaphore
import time
def task():
sm.acquire()
print(f'{currentThread().name} 在执行')
time.sleep(3)
sm.release()
sm = Semaphore(5)
for i in range(15):
t = Thread(target=task)
t.start()