スレッドロック
状況のリソースをつかむために1.複数のスレッド:
ロックは、通常、共有リソースへのアクセスを同期するために使用されています。あなたは、リソースへのアクセスのロックオブジェクトを取得するメソッドを取得呼び出す必要があるとき、各オブジェクトへの共有リソースを作成するロックリソースへのアクセスが終了するまで(他のスレッドが既にロックを取得した場合、現在のスレッドは、それが解放されるのを待つ必要があります)その後、ロックを解除し、リリースメソッドを呼び出します。
ケースI:
from threading import Thread,Lock
import time
K = Lock()
def func():
global n
K.acquire() # 加锁
team = n
time.sleep(0.1) # 分析:第一个线程刚拿到team = n = 100,就遇到阻塞,马上切换到下一个线程,下一个线程还是跟上一个线程一样的情况,
# 由于线程切换速度很快,一直拿到的team都是99,除非你的线程数量足够大。
# 解决方法: 给处理数据部分进行加锁处理。
n = team-1
K.release() # 释放锁
if __name__ == '__main__':
n = 100
l = []
for i in range(100):
t = Thread(target=func)
l.append(t)
t.start()
for t in l:
t.join()
print(n)
ケースII:
from threading import Thread,Lock
x = 0
K = Lock()
def func():
global x
K.acquire()
for i in range(60000):
x = x+1
# t1 的x刚拿到0 保存状态 就被切换了
# t2 的x拿到0 进行+1操作 x = 1
# t1 又获得了运行 ,返回被切之前的保存状态,x=0+1 x= 1
# 其实运算出来的数字应该是+2,实际上只+1
# 这就产生了数据安全问题
K.release()
if __name__ == '__main__':
t1 = Thread(target=func)
t2 = Thread(target=func)
t3 = Thread(target=func)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(x)
第二に、デッドロック
デッドロックは:実装プロセス内の2つの以上のプロセスまたはスレッドの現象を指し、お互いを待っによって引き起こされるリソースの競合の結果は、外力のない状態で、彼らはそれを促進することができません。このとき、次のようにデッドロックがあると、システムがデッドロックと呼ばれる別のプロセスを待っているの過程で常にデッドロックを生成するために、デッドロック状態またはシステムであると言います
from threading import Lock as Lock
import time
mutexA=Lock()
mutexA.acquire()
mutexA.acquire()
print(123)
mutexA.release()
mutexA.release()
ソリューションは、再帰的なロックは、同じリソースに対する同一スレッド複数のリクエストで、Pythonのを支援するために、PythonはリエントラントロックRLOCKを提供します。
この内部RLOCKはロックとカウンタ変数を維持したリソースは多くの時間が必要になることができるように、カウンタは、回獲得数を記録します。すべてがリリースされるまで、リソースを取得するために他のスレッドをスレッドを取得します。もし代わりにRLOCKロックを使用して上記の例では、デッドロックは発生しません。
from threading import Thread,RLock,currentThread
import time
k1 = k2 = RLock() # 一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
class Myt(Thread):
def run(self):
self.task1()
self.task2()
def task1(self):
k1.acquire()
print(f'{self.name} 抢到了 锁1')
k2.acquire()
print(f'{self.name} 抢到了 锁2')
k2.release()
print(f'{self.name} 释放了 锁2')
k1.release()
print(f'{self.name} 释放了 锁1')
def task2(self):
k2.acquire()
print(f'{self.name} 抢到了 锁2')
time.sleep(1) # 当线程1 执行到这一步的时候,遇到阻塞,马上切换到线程2,此时,线程1已经拿到了锁2,但是线程2也要拿,所以形成了死锁。
k1.acquire() # 解决方法: 加入递归锁RLock
print(f'{self.name} 抢到了 锁1')
k1.release()
print(f'{self.name} 释放了 锁1')
k2.release()
print(f'{self.name} 释放了 锁2')
for i in range(3):
t = Myt()
t.start()
第三に、信号量セマフォ
のプロセスと同様に
内蔵カウンタのセマフォ管理、
呼が取得するたびに()カウンタ1に内蔵、
内蔵リリース()を呼び出しカウンタ+1、
カウンタが0以上である、別のスレッドがスレッドを起動するまで、カウンタが0である場合、取得()はブロックされますリリース()。
例:(のみ5つのスレッドが5への接続の最大数を制限することができ、セマフォ取得できている間)
from threading import Thread,currentThread,Semaphore
import time
def func():
sm.acquire()
print(f'{currentThread().name} 正在执行')
time.sleep(3)
sm.release()
sm = Semaphore(5)
for i in range(15):
t= Thread(target=func)
t.start()
四、GILロック:
GIL:グローバルインタプリタロック。各スレッドは1つのスレッドだけのコードを実行できることを保証するために実装プロセスでGILを取得する必要があります。
GILとロック、2つのロックされている本質的には、ミューテックスロックデータであり、保護が同じではありませんが、かつてのインタプリタレベル(もちろんのは、そのようなデータのガベージコレクションとして、データ保護のインタプリタレベルである)であり、アプリケーションデータは、ユーザー自身の発展を保護するために、GILは唯一のロックユーザー定義のロックを扱うことができ、この問題の責任ではないことは明らかです
プロセス分析:すべてのスレッドが権限を実行しているGILはロックすべてのスレッドをつかむ、またはつかみます
その後、スレッド1グラブGILロック、実行権限を取得し、実行、および一握りのロックを追加し、まだ完成し、そのスレッド1がロックを解除されていないていない、スレッド2はGILロックをつかむ可能性があり、実行のプロセスを開始ロックは、スレッド2は、実行ブロックされたアクセス権が奪われているに入り、スレッド1を解放することが見出されていなかった、スレッド1 GILを取得して、ロックを解除する通常行うことが可能となります。。。これは、シリアル動作の効果につながります
それはシリアルですので、我々は実行します
t1.start()
t1.join
t2.start()
t2.join()
これは、ああ、なぜt1が実行されたコード、すべてのコードロックT1の同等のすべてを待っている参加知り、それをロックする追加シリアル実行され、かつロックコードは、共有データをロックする操作の一部でしかありません。
第五に、計算集約
科学計算処理等は、CPUタイプの連続使用を必要とします。
from multiprocessing import Process
from threading import Thread
import os,time
res = 0
def func():
global res
for i in range(10000000):
res += i
if __name__ == '__main__':
print(os.cpu_count()) # CPU核心数
start = time.time()
l = []
for i in range(4):
# t = Process(target=func)
t =Thread(target=func)
l.append(t)
t.start()
for t in l :
t.join()
end = time.time()
print(end-start) # 多进程耗时:3.4384214878082275 多线程耗时:4.417709827423096
上から見た:処置は、マルチプロセス、マルチスレッドよりもCPUの処理速度の高速演算コード長期使用を継続します。マルチプロセス操作にもおすすめ。
六、IO集約型
閉塞を引き起こす可能性がIO操作のような治療のタイプを指し
from multiprocessing import Process
from threading import Thread
import time
def func():
time.sleep(5)
if __name__ == '__main__':
l = []
start = time.time()
for i in range(4):
# t = Process(target=func) # 多进程
t = Thread(target=func) # 多线程
l.append(t)
t.start()
for t in l:
t.join()
end = time.time()
print(end-start) # 多进程:5.8953258991241455 多线程:5.002920150756836
上記から分かるように、このタスクは、複数のプロセスよりも有意にマルチスレッド高速IOオペレーションの閉塞を引き起こす場合。
上記2例から、それは結論付けました。
計算集約型のタスクのためのpythonは、マルチスレッドの効率を開き、(スイッチングの多くではない)、シリアルよりも優れた性能を強化する方法について持ち込むことはできませんが、効率IO集約型のタスクのためか、大幅に改善しています。こうしたソケット、爬虫類、ウェブとして、IO集約型のためのマルチスレッドな財務分析などの計算集約型のための複数のプロセス、