わかりやすいDispatchSemaphore
2080 ワード
DispatchSemaphore
信号量は、同時アクセスリソースを制御するためのメカニズムであり、マルチスレッドに多く用いられ、同時スレッド数を制御することができる.
例
let queue = DispatchQueue.global()
var arr = [Int]()
for i in 0..<10000 {
queue.async {
print("add \(i)")
arr.append(i)
}
}
実行結果:一定時間実行後、プログラムcrash crash原因分析:Arrayはスレッドが安全ではなく、マルチスレッドが同時にArrayを操作してcrashを招く
let semaphore = DispatchSemaphore(value: 1)
let queue = DispatchQueue.global()
var arr = [Int]()
for i in 0..<10000 {
queue.async {
if semaphore.wait(timeout: .distantFuture) == .success {
print("add \(i)")
arr.append(i)
semaphore.signal()
}
}
}
運転結果:正常に動作し、
arr
にデータが正常に追加されました注意:arr
のデータは0~9999という順序で厳密に追加されたものではありません例解析
let semaphore = DispatchSemaphore(value: 1)
valueは初期値を表し、ここでは1の別の解釈に設定します.WCには穴が1つしかありません.
if semaphore.wait(timeout: .distantFuture) == .success
semaphore
の値が0でない場合、上記の関数はsuccess
を返し、semaphore
の値を1減少させる.0の場合、スレッドはtimeout
まで待機します(関数は返されず、次のコードは実行されません).timeout
は待ち時間の最大時間を制御することができ、.distantFuture
は永久待ち時間を表すように設定される.もう一つの解釈:一人の客が来て、もし穴があれば、占めて、穴の数-1、さもなくば前の客が使い終わって離れるのを待っています
semaphore.signal()
semaphore
の値+1を、この時点で他の待機中のスレッドが起動されて実行される(同じ優先度でランダムに起動する)別の解釈:お客様が使用済みになって離れ、ピット数+1まとめてみる
wait
はsuccess
を返し、if
文内のコードを実行するとともに、信号量が0に減少するより厳密にはqueue
中の非同期taskが最初に実行されたとき、第1のtaskは必ずしも第1サイクルで追加するそのif
内のコードがまだ実行されていないと仮定する)し、後のサイクルはif
文内のsemaphore.signal()
コードが実行されると、信号量の値は1となり、1となる.したがって、現在待機中のスレッドのいずれかが起動して実行され、他のスレッドは以上、もし問題があれば、指摘を歓迎して、感謝しきれません...