ホームページ  >  記事  >  バックエンド開発  >  マップされた変数を新しいマップされたオブジェクトに置き換えることはスレッドセーフですか?

マップされた変数を新しいマップされたオブジェクトに置き換えることはスレッドセーフですか?

WBOY
WBOY転載
2024-02-10 16:33:12867ブラウズ

マップされた変数を新しいマップされたオブジェクトに置き換えることはスレッドセーフですか?

php エディタ Apple は、「マッピング変数を新しいマッピング オブジェクトに置き換えるのはスレッドセーフですか?」というよくある質問に答えます。マッピング変数は一般的なデータ構造です。キーと値のペアを保存します。マルチスレッド環境では、スレッドの安全性が重要な考慮事項になります。新しいマッピング オブジェクトを使用すると同時アクセスの問題を回避できますが、スレッドセーフであるかどうかはケースバイケースで評価する必要があります。次に、読者がスレッド セーフとマップされたオブジェクトの関係をよりよく理解できるように、この問題を詳しく調査します。

質問内容

マッピングされたオブジェクトが機械語より大きく、golangがスレッドセーフであることを保証していないため、スレッドセーフではないと思います。しかし、go run -race main.go を使用してデモ コードを実行すると、エラーは報告されません。これが、threadsanitizer が実行時チェックと代入操作に依存して、スレッドの安全でない条件を満たすことが難しい理由である可能性があります。

サンプルコードは次のとおりです:

リーリー

それでは、同時実行エラーを引き起こすようにコードを変更するにはどうすればよいでしょうか?それとも私が間違っていて、コードはスレッドセーフなのでしょうか?

解決策

注意すべき点がいくつかあります:

リーリー

Range 式は、for ループの先頭で 1 回評価されます。したがって、この操作は m を 1 回読み取ります (これは、ループ内のコードが m を再割り当てすると、ループは元の m を繰り返し続けることを意味します。ただし、新しい要素が追加された場合、または m から要素が削除された場合、これらはループによって検出されます)、ループ自体が fmt.println を呼び出し、実行のほとんどを消費します。このゴルーチンの時間。ゲームの最新情報を知りたい場合は、削除してください。

第二に、実際には 2 番目のマップを初期化する必要はありません。

これらの操作を実行して競合検出機能を実行すると、データ競合が検出される可能性があります。私に関する限り、そうです。

人種検出器は、人種を検出すると、人種について不平を言います。したがって、一致が報告された場合は、一致があります。報道されなかったとしても、コンテストがないわけではありません。

私のプラットフォームでは、マップ変数自体は実際には機械語と同じサイズです。これはマップされた構造体への単なるポインターです。したがって、マップされた変数への書き込みは事実上アトミックです。つまり、このプラットフォームでは部分的に割り当てられたマップは表示されません。ただし、他のゴルーチンがこのメモリ書き込みをいつ認識するかという保証はないため、これによって競合が防止されるわけではありません。

一言で言えば、これは競争です。これはマップ変数のサイズが原因ではありません。この問題を解決するには、ミューテックスを使用します。

以上がマップされた変数を新しいマップされたオブジェクトに置き換えることはスレッドセーフですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。