追加は複数のゴルーチンによる同時使用に対してスレッドセーフではありませんか?
ゴルーチンを使用してループ内のスライスにデータを同時に追加する場合、要素の欠落や重複などの不一致が発生する可能性があります。このシナリオでは、append 関数が複数のゴルーチンによる同時使用に対してスレッドセーフではないのかどうかという疑問が生じます。
答え: データ競合とスレッド セーフの欠如
Go では、スライス (より具体的にはスライス ヘッダー) を含め、同時読み取り/書き込みに対して安全な値はありません。複数のゴルーチンが同じスライスを同時に変更しようとすると、データ競合が発生し、予期しない動作につながる可能性があります。
データ競合検証
コードは - を使用して実行できます。データ競合の存在を確認するためのレース オプション:
go run -race play.go
解決策:同期
この問題を解決し、データの一貫性を確保するには、要素を同時に書き込むときにスライスへのアクセスを同期する必要があります。これは、sync.Mutex:
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()
を使用して実現できます。スライスに追加する前にミューテックスを取得し、その後解放することで、一度に 1 つのゴルーチンのみが書き込みアクセスできるようになり、データの破損を防ぐことができます。
結論
スライス要素は個別の変数として動作し、変更できます同時に、スライス ヘッダーは本質的にスレッドセーフではありません。安全で一貫性のある同時書き込み操作を保証するには、ゴルーチン内のスライス ヘッダーを変更するときに、ミューテックスやチャネルなどの同期メカニズムを採用することが重要です。
以上がAppend 関数は、Goroutine の同時使用に対してスレッドセーフですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。