GILグローバルインタープリタロック
官方解释: CPythonのではグローバルインタプリタロック、または GIL、ある複数防止ミューテックス ネイティブスレッドから一度Pythonのバイトコードを実行します。このロックは、ある主必要 はCPythonのメモリ管理があるためである ではないスレッドセーフ。
素晴らしい翻訳者:
Pythonインタプリタ、多くがあり 、最も一般的にはCPythonのインタプリタでの
GILの本質は、ミューテックスです:データのセキュリティを確保するために、シリアル犠牲効率となっ同時が
同時に同じプロセスで複数のスレッドを防ぐために使用されます(実行、同じプロセスの複数のスレッド内ではなく、同時達成するために並行して達成することはできませんが)
、メモリ管理CPythonのインタプリタは、スレッドセーフではありませんので、GILがある存在ガベージコレクションのメカニズムから安全ではない、我々は、各プロセスになりますメモリ管理スレッド
プロセスでのpythonだけでなく、メインスレッドtest.pyまたは別のスレッド開発のメインスレッド、ならびにインタプリタインタプリタレベルのスレッドとリサイクルによって開かは、要するに、すべてのスレッドは、このいずれかで実行されています。プロセス内で
実行するためにパスコードをインタプリタに必要な義務のすべてのスレッドなので、我々は最初に解決しなければならないことはインタプリタコードにアクセスする能力であります
あなたが複数のスレッドを対象とした場合= 作品名の実装プロセスは、次のとおりです。
複数のスレッドが最初の許可を取得するために実行されるインタプリタコードに訪れ、その後、コード実行インタプリタにターゲットコードは、インタプリタ・コードは、すべてのスレッドです共有、およびスレッドを回収することも、離れてインタプリタコードの実行にアクセスすることができる
という問題につながる:合計データ 100、実行スレッド1 X = 100は、同時に、ガベージコレクションの実装は、回収され100操作なので、唯一のタスクコードを実行することができ、同時に、GILロックを追加するPythonインタプリタを確保する必要性
問題:pythonのマルチスレッドは、多くの利点を使用することはできませんが、無用ではありません
A:Pythonのマルチスレッドが必要ポイントを議論することに有用であるかどうかを調査
例: 1 つの計算集約的なタスク、それぞれ10S。 単核状況: オープン・スレッドより省資源 マルチコア場合: オープン10Sプロセス オープンスレッド40代 2 。4 IO集中型のタスク、各10S 単球の状況: オープンスレッド省資源、より マルチコア条件: オープンスレッドより省資源
マルチプロセッシングインポートプロセス からスレッドインポートスレッド インポート時間、OSの #计算密集型 DEF FUNC(): RES = 0 のための I における範囲(10000 ): RES * = 1 #IO密集型DEF FUNC(): time.sleep ( 3 )場合__name__ == ' __main__ ' : 印刷(os.cpu_count()) リスト = [] 開始 = time.time()の ための I にレンジ(4 ): P- =プロセス(目標= FUNC) #マルチプロセス #数値計算実行時間:0.21994638442993164 #IO集約実行時間:3.2253575325012207 P- =スレッド(目標= FUNC)#マルチスレッド #のランタイム:0.003988504409790039 #IO集約型の実行時間:3.0033791065216064 list.append(P-) p.start() のための p型で一覧: p.join() #のスレッドの実行が終了した後に実行されているすべての子供/子供のための待ち時間メインコース/メインスレッド 終了= time.time() 印刷(' ファイル名を指定して実行時間:S%'%(エンド- スタート))
デッドロック/再帰的ロック
これは、実装プロセス内の2つのプロセスまたはスレッド、お互いを待っているの現象によるリソースの競合の結果を参照します。
注意:私は簡単にロックを処理しません。
RLOCK再帰的ロック
RLOCKは、連続的にロックを取得および解放する最初の人を取得することができる
それぞれ1つによってロック本体カウント取得
それぞれ一つによってロック本体カウントを解放する
限り、ロックカウントがゼロでないように、他のプロセス/スレッドではありません掴みます
スレッディングインポートスレッドは、ロック インポート時間 #は、2つのロック発生 mutexA = ロック() mutexB = ロック() クラスMyThread(スレッド): DEF RUN(セルフ): self.func1() self.func2() DEF 関数func1(セルフ): mutexA.acquire() 印刷(' %Sはロックつかんだ' self.name%)を #self.name同等current_thread()、名前 mutexB.acquire() 印刷(" %SがBグラブロック"%self.name) mutexB.release() プリント(' %S Bのロック解除'%self.name) mutexA.release() プリント(' %のSロック解除'%self.name) DEFの関数func2(セルフ): mutexB.acquire() プリント(' %SのBグラブロック'%self.name) time.sleep( 1 ) mutexA.acquire() プリント(' %は、Sロックつかん'%をself.name) mutexA。リリース() 印刷(' %Sロック解除'%self.name) mutexB.release() プリント(' %S Bのロック解除'%self.name) のための I における範囲(10 ): Tは = MyThreadを() t.start () #再帰的なロック からスレッディングインポートスレッド、RLOCK mutexA = mutexB = RLOCK() クラスMyThread(スレッド): DEF RUN(セルフ): self.func1() self.func2() DEF関数func1(セルフ): mutexA.acquire() 印刷(' %Sはロックつかんだ' self.name%)を #self.name同等current_thread()、名前 mutexB.acquire() 印刷(" %SがBグラブロック'%self.name) mutexB.release() 印刷(' %S Bのロック解除'%self.name) mutexA.release() プリント(' %のSロック解除'%self.name) DEFの関数func2 (自己): mutexB.acquire() 印刷("ロック%S Bつかん'%self.name) time.sleep( 1 ) mutexA.acquire() プリント(' %sはロックつかん'%をself.name) mutexA.release() 印刷(' %の放出ロック'%self.name) mutexB.release() プリント(' %S Bロック解除'%self.name) のための I における範囲(10 ): T = MyThread() t.start()
セマフォ
ミューテックス:ロックの鍵
セマフォ:マルチロックキー
スレッディングインポートスレッド、セマフォ インポート時間 インポートランダム SEM =セマフォは(5) #は5キーロックを生成 DEF FUNC(名): sem.acquire()印刷(「の%のSの扉」%の名称) の時間。 SLEEP(random.randint( 1 ,. 3 )) sem.release()印刷(' 外出する%S '%の名を)するために I でレンジ(10 ): Tはスレッドを=(対象= FUNC、引数の= (I) ) t.start()
イベントイベント
e.set() 发信号
e.wait() 等待信号
from threading import Thread, Event import time e = Event() def light(): print('红灯') time.sleep(3) e.set() print('绿灯') def car(name): print('%s等红灯'%name) e.wait() print('%s开车了'%name) t = Thread(target=light) t.start() for i in range(10): t = Thread(target=car, args=('车手%i'%i, )) t.start()
同一个进程下的多个线程本来就是数据共享,为什么还要用队列?
因为队列是 管道+锁,使用队列就不需要自己动手操作锁的问题
import queue q = queue.Queue() q.put('one') q.put('two') q.put('three') print(q.get()) # >>> one 先进先出 q = queue.LifoQueue() q.put('one') q.put('two') q.put('three') print(q.get()) # >>> three 堆栈 先进后出 q = queue.PriorityQueue() # 数字越小,优先级越高 q.put((10, 'one')) q.put((1, 'two')) q.put((5, 'three')) print(q.get()) # >>> (1, 'two')