文字列の不変性と同時実行性
質問:
文字列への書き込みを同期する必要がありますか?文字列が不変であることを考えると、複数のスレッドからの読み取りと書き込みの間で一貫した状態が保証されているのではありませんか?
答え:
Go の文字列値は確かに不変です。つまり、作成後にコンテンツを変更することはできません。ただし、この不変性は文字列値自体にのみ適用され、文字列を保持する変数には適用されません。
変数は変更可能であり、時間の経過とともに異なる文字列値を指すことができます。複数のゴルーチンが文字列変数に同時にアクセスし、そのうちの少なくとも 1 つがそれに書き込む場合は、同期が必要です。これにより、変数への書き込みが確実に順番に実行され、文字列の値ではなく変数への同時アクセスが防止されます。
例:
次のコードを考えてみましょう:
<code class="go">var s string = "hello" func writeToString(s string) { s = "goodbye" } func main() { wg := sync.WaitGroup{} const num = 10 for i := 0; i < num; i++ { wg.Add(1) go func(i int) { defer wg.Done() writeToString(s) }(i) } wg.Wait() fmt.Println(s) }</code>
同期を行わないと、複数のゴルーチンが文字列を保持する変数に書き込むため、このコードではデータ競合が発生します。その結果、s の最終値は、どのゴルーチンが最後に変数にアクセスしたかに応じて、「hello」または「goodbye」のいずれかになります。
sync.Mutex などの同期を使用することで、一度に 1 つのゴルーチンが変数に書き込み、期待される動作を維持できます。
以上がGo の不変文字列には同時書き込みの同期が必要ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。