ホームページ > バックエンド開発 > Golang > Go でのスライスへの追加がスレッドセーフではないのはなぜですか?

Go でのスライスへの追加がスレッドセーフではないのはなぜですか?

Susan Sarandon
リリース: 2024-11-09 17:30:02
オリジナル
284 人が閲覧しました

Why is appending to slices in Go thread-unsafe?

スライスへの追加がスレッドセーフではない理由

複数のゴルーチンがスライスにデータを同時に追加しようとすると、データ競合状態が発生する可能性があります。起こる。これは、Go のスライスがスレッドセーフではないためです。つまり、複数のゴルーチンが同じスライス ヘッダーに同時にアクセスして変更することができ、データ破損を引き起こす可能性があります。

データ競合の図

次のコードを考えてみましょう:

destSlice := make([]myClass, 0)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        destSlice = append(destSlice, tmpObj)
    }(myObject)
}
wg.Wait()
ログイン後にコピー

このコードでは、複数のゴルーチンが同時に destSlice スライスに追加されます。ゴルーチンは操作をインターリーブし、互いの変更を上書きする可能性があるため、結果のスライスでデータが欠落したり空白になったりする可能性があります。

「-race」オプションによるデータ競合の検証

「-race」オプションを指定してコードを実行すると、データ競合が検出されるたびに警告が生成されます。次の出力は、提供されたコードのデータ競合状態を示しています。

==================
WARNING: DATA RACE
Read at 0x00c420074000 by goroutine 6:
  main.main.func1()
      /home/icza/gows/src/play/play.go:20 +0x69

Previous write at 0x00c420074000 by goroutine 5:
  main.main.func1()
      /home/icza/gows/src/play/play.go:20 +0x106

Goroutine 6 (running) created at:
  main.main()
      /home/icza/gows/src/play/play.go:21 +0x1cb

Goroutine 5 (running) created at:
  main.main()
      /home/icza/gows/src/play/play.go:21 +0x1cb
==================
ログイン後にコピー

解決策: 同期にミューテックスを使用する

スレッドセーフな同時追加を確保するには、次のようにします。ミューテックスを使用して destSlice スライス ヘッダーを保護できます。次の変更されたコードは、これを示しています。

var (
    mu        = &sync.Mutex{}
    destSlice = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        mu.Lock()
        destSlice = append(destSlice, tmpObj)
        mu.Unlock()
    }(myObject)
}
wg.Wait()
ログイン後にコピー

各追加操作の前にミューテックスを取得することで、複数のゴルーチンが同時にスライス ヘッダーを変更するのを防ぎ、データの整合性を確保し、データ競合状態を排除します。

以上がGo でのスライスへの追加がスレッドセーフではないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート