golang同時ロック

2252 ワード

本稿では,golangにおける同時およびgolangのロックメカニズムについて学習する.
まず,このようなシーンを仮定し,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は永遠に待つかもしれない.