golang同時ロック
2252 ワード
本稿では,golangにおける同時およびgolangのロックメカニズムについて学習する.
まず,このようなシーンを仮定し,2つのコヒーレンスがあり,同時に1つの数字を読み書きし,それぞれそれを増減し,コードは以下の通りである.
このコードを実行すると、私たちは何も出力していないことに気づきました.理由は簡単で、メインプログラムは2つの協程を作成した後、終了しました.メインプログラムを終了しないようにsyncを使用します.WaitGroup
しかし、プログラムが走り出した結果は1ではなく、毎回走り出すのとは異なる.実は、併発したことがある同級生は原因を知っています.現在の変数値が1であると仮定し、コヒーレンスaは1を加算しようとすると、コヒーレンスaはまず1を読み出し、1を加算して2を得るが、2という値が変数に書き込まれる前に、コヒーレンスbは変数を読み出したが、このとき変数は依然として1であり、bはこの1を取得して0を減算する.この場合,協程1が先に書き戻されても協程bが先に書き戻されても,我々が得た結果は間違っている.正しい結果を得るには、ロックをかけることが最も一般的です.golangではsyncを使用できます.Mutex
1つの協程がmapを書いているとき、他の協程がこのmapを読んだり書いたりしようとすると、プログラムは直接crash!!!多くの人がこのデザインにツッコミを入れていますが、このデザインは少なくともプログラマーにすぐに問題を発見する機会を与えたと思います.鍵をかけましょう少年.
デッドロックは、1つのタスクを完了するリソースが2つ(または複数)の異なるスレッドによってそれぞれ占有され、すべてが待機状態で完了できないと理解できます.
活性ロックの例は、2つ以上のコヒーレンスが実行時にそれぞれ一部のリソースを占有して実行できないことである.そこで彼らはリソースを解放して再要求したが、衝突し続け、実行できなかった.
飢餓の例は、トランザクションT 1がデータRをブラックアウトした場合、トランザクションT 2がまたブラックアウトRを要求し、T 2が待つことである.T 3もブラックアウトRを要求し、T 1がR上のブラックアウトを解放した後、システムはまずT 3の要求を承認し、T 2は依然として待機している.そしてT 4はまたRのブラックアウトを要求し、T 3がR上のブラックアウトを解放した後、システムはまたT 4の要求を承認した......T 2は永遠に待つかもしれない.
まず,このようなシーンを仮定し,2つのコヒーレンスがあり,同時に1つの数字を読み書きし,それぞれそれを増減し,コードは以下の通りである.
func main(){
a := 1
p_a := &a
go func(p_a *int){
for i := 1; i < 100000; i++ {
*p_a += 1
fmt.Println(*p_a)
}
}(p_a)
go func(p_a *int){
for i := 1; i < 100000; i++ {
*p_a -= 1
fmt.Println(*p_a)
}
}(p_a)
}
このコードを実行すると、私たちは何も出力していないことに気づきました.理由は簡単で、メインプログラムは2つの協程を作成した後、終了しました.メインプログラムを終了しないようにsyncを使用します.WaitGroup
func main(){
a := 1;
p_a := &a;
var wg sync.WaitGroup
wg.Add(2)
go func(p_a *int){
for i := 1; i < 100000; i++ {
*p_a += 1
}
wg.Done()
}(p_a)
go func(p_a *int){
for i := 1; i < 100000; i++ {
*p_a -= 1
}
wg.Done()
}(p_a)
wg.Wait()
fmt.Println(*p_a)
}
しかし、プログラムが走り出した結果は1ではなく、毎回走り出すのとは異なる.実は、併発したことがある同級生は原因を知っています.現在の変数値が1であると仮定し、コヒーレンスaは1を加算しようとすると、コヒーレンスaはまず1を読み出し、1を加算して2を得るが、2という値が変数に書き込まれる前に、コヒーレンスbは変数を読み出したが、このとき変数は依然として1であり、bはこの1を取得して0を減算する.この場合,協程1が先に書き戻されても協程bが先に書き戻されても,我々が得た結果は間違っている.正しい結果を得るには、ロックをかけることが最も一般的です.golangではsyncを使用できます.Mutex
var l sync.Mutex
func main(){
a := 1;
p_a := &a;
var wg sync.WaitGroup
wg.Add(2)
go func(p_a *int){
for i := 1; i < 100000; i++ {
l.Lock()
*p_a += 1
l.Unlock()
}
wg.Done()
}(p_a)
go func(p_a *int){
for i := 1; i < 100000; i++ {
l.Lock()
*p_a -= 1
l.Unlock()
}
wg.Done()
}(p_a)
wg.Wait()
fmt.Println(*p_a)
}
golangの中のmap
1つの協程がmapを書いているとき、他の協程がこのmapを読んだり書いたりしようとすると、プログラムは直接crash!!!多くの人がこのデザインにツッコミを入れていますが、このデザインは少なくともプログラマーにすぐに問題を発見する機会を与えたと思います.鍵をかけましょう少年.
デッドロック
デッドロックは、1つのタスクを完了するリソースが2つ(または複数)の異なるスレッドによってそれぞれ占有され、すべてが待機状態で完了できないと理解できます.
活性ロックの例は、2つ以上のコヒーレンスが実行時にそれぞれ一部のリソースを占有して実行できないことである.そこで彼らはリソースを解放して再要求したが、衝突し続け、実行できなかった.
飢餓の例は、トランザクションT 1がデータRをブラックアウトした場合、トランザクションT 2がまたブラックアウトRを要求し、T 2が待つことである.T 3もブラックアウトRを要求し、T 1がR上のブラックアウトを解放した後、システムはまずT 3の要求を承認し、T 2は依然として待機している.そしてT 4はまたRのブラックアウトを要求し、T 3がR上のブラックアウトを解放した後、システムはまたT 4の要求を承認した......T 2は永遠に待つかもしれない.