簡単に把握できるマルチスレッド--pythonマルチスレッド競合リソースによるプログラムクラッシュの解決策について


マルチスレッドを使用する場合、マルチスレッド競合システムリソースを考慮する場合、通常、信号量制御のようなロック(Lock)を使用して、同じ時間にリソースを変更するスレッドへのアクセスを制限します.PCデスクトップレベルのプログラム開発では,共有リソースデータの同期の問題が特に重視される.次に,信号量を用いた方法でマルチスレッドアクセス共有データを制御する例を示す.共有データcounterカウンタの定義
global counter
counter=0

Task作業内容を定義し、作業を実行する場合、counterカウンタ+1
class Task:
	#     Task    ( )
	def dojob(self):
		global counter
		counter=counter+1
		pass

信号量を設定します.
#                    
semaphore=threading.BoundedSemaphore(1)

信号量制御マルチスレッドを使用して共有データにアクセスします.
class Task:
	def dojob(self):
		global counter
		counter=counter+1
		pass
		
	#                
	def syncupdate(self):
		#  
		semaphore.acquire()
		#    
		self.dojob()
		#   
		semaphore.release()

スレッドエントリ関数の設定
#    
def schedule(tid, task:Task):
	print('Task['+str(tid)+'] started.')
	#task.dojob()	#        ,     ,     
	task.syncupdate()

マルチスレッド実行tasksの作成
import threading
#        
threadpool=[]
#tasks    
tasks=[...]
for tid in range(len(tasks)):
	#    ,         
	t=threading.Thread(target=schedule, args=(tid, tasks[tid]))
	threadpool.append(t)
	t.start()
for t in threadpool:
	#      
	t.join()

ここでcounterカウンタは共有リソースであり,アクセスするたびに信号量semaphoreを用いてアクセスを取得する権限が必要である.
semaphore.acquire()

共有リソースを使用しているスレッドがある場合、他のスレッドは待機状態になります.共有リソースの変更が完了するたびに、信号量によって制御アクセス権が解放されます.
semaphore.release()

信号量制御マルチスレッドの使用はほぼ完了した.以前は初心者をめちゃくちゃにしていたマルチスレッドが、今から見れば、簡単すぎるようです.so easy!
そう思うと、あなたは大間違いです!一つのプログラムの実行のため、多くのものが含まれています.プログラムは、移植性の有無にかかわらず、まず特定のプラットフォームに基づいています.プログラム実行には、内部および外部のリソースが必要です.内部リソースをソフトウェア実行アーキテクチャ、外部リソースをオペレーティングシステムおよび関連プラットフォームアーキテクチャとして定義します.通常、ソフトウェア開発サイクルでは、ソフトウェア実行アーキテクチャの問題を考慮し、オペレーティングシステムおよび関連プラットフォームアーキテクチャの関連は想定できない.ソフトウェア設計は静的であり、実際の状況でリアルタイムで動的に現れる意外なことを考慮することは難しい.
実際、プログラム実行の各ステップは、メモリリソースに関連する変数定義から関連オペレーティングシステムリソースに付与されたウィンドウの変動まで、システムリソースの競合に関連しています.リソースの割り当てと解放は、オペレーティングシステムおよび関連プラットフォームがリアルタイムのスケジューリングを実行する必要があり、時間に関連しています.現実の中で、多くのプログラマーはいくつかの“古い油条”がすべて犯す1つの間違いを含みます:CPUのスピードはとても速くて、プログラムのあるいくつかのステップを時差なく“瞬間”完成させるのに十分です.これはメモリリソース割り当ての一般的な基本タイプ変数では,基本的に正しいと考えられる.オペレーティングシステムおよび関連システムに関するソフトウェアプラットフォームに配置すると、これは大きな「エラー」です.リソース割り当てに関する「リアルタイム」のシステムソフトウェア操作は、完全にリアルタイムではないためです.オペレーティングシステムを学んだことがある人は、この言葉の意味を理解しなければならない.CPUの「リアルタイム」動作の本質は、時間管理とリソーススケジューリングである.ただ、CPUの速度は人間の脳に比べてずっと速く反応しているので、「リアルタイム」だと思われます.CPUの本質はタイムスライス競合リソースである.いくつかの敏感な資源の競争の中で、特に明らかです.システムリソースが「長い」場合でも、「リアルタイム」の観点で問題を考慮すると、推定しにくい事故が発生する可能性があります.
マルチスレッドが機密システムリソースを競合させる場合、要求の速度は非常に速いが、システムがリソースを割り当てて解放し、使用するプロセスは相対的に「遅い」.CPUクロックの誤差により事故が発生する可能性が高い.コンピュータの時間計算は,実際にはCPUクロックに関連付けられていることを知っている.CPUクロックは非常に正確であるにもかかわらず、誤差が小さい可能性がある.システムプラットフォームにバグがあることも可能です.これにより、システムの機密リソースの割り当てと解放に異常が発生します.「タイムリーではありません.」これは実践的に検証されたものだ.
このようなcatch/exceptでキャプチャできないexception異常–fatal errorが発生した場合、システムの機密リソースの割り当てと解放に問題が発生する可能性が高いことを考慮してください.以上のコードは,リソースの競合矛盾がないため,単一スレッドで実行する場合に異常はない.マルチスレッドで実行すると、機密システムリソースに関連する場合、プログラムのクラッシュを引き起こす可能性が高い.どうすればいいの?CPU実行はCPUタイムスライス(CPU Time)の競合であることが知られている.要求されたタイムスライスとリソースを使用するタイムスライスの差が大きいとシステム異常を引き起こしやすく、使用遅延の方法が考えられる.ミリ秒msはシステム時間の正確な単位である.任意の整数ミリ秒(規則に適合)の遅延を用いて,CPUクロック誤差とシステム時間差バグによる異常なクラッシュを回避できた.従って、キー位置で遅延動作コードを用いて時間誤差補正を行うことができる.
time.sleep(1)
#time.sleep(.1)

上記マルチスレッドコードについては、
#                
	def syncupdate(self):
		#  
		semaphore.acquire()
		#    1 :        
		time.sleep(1)
		#    
		self.dojob(self)
		#   
		semaphore.release()

これで、マルチスレッドの「悪意のある」競合リソースによるプログラムクラッシュについて完璧に解決しました.後記:実際には、マルチスレッドの「悪意のある競争」に関する文章が根本的な原因を論じていることは少ない.そのことしか知らない.Javaでsynchronizedを使用して非同期スレッドを制限するのも同様です.一般的な基本タイプでは問題ありませんが、実際の環境に導入され、システムの機密リソースの割り当てスケジューリングに関連しているとは言い難いです.このような文章は度娘の検索がかなり少なく,いくつかの編を添付している.附:smking:マルチスレッド同時アクセスで発生する可能性のあるクラッシュ問題柳コン鵬:マルチスレッドアクセスによるクラッシュの一例sinat_41685845:マルチスレッドクラッシュ(一)