6

C または C++ プログラムで、2 つのスレッドが同じグローバル変数を使用する場合、ミューテックスを介して変数をロックする必要があります。

しかし、具体的にどのような場合に?

  1. スレッド 1: 読み取り スレッド 2: 読み取り
  2. スレッド 1: 書き込み スレッド 2: 読み取り
  3. スレッド 1: 書き込み スレッド 2: 書き込み

もちろん、ケース 3 でロックする必要がありますが、他の 2 つのケースは何ですか? ケース 2 (非アトミック操作の場合) ではどうなりますか? ある種のアクセス違反がありますか、それともスレッド 2 が古い値を取得するだけですか? ハードウェアレベルのメモリとレジスタに同時にアクセスできないため(通常のPCハードウェアでは)、または並列RAMチップへの並列バスラインを備えたある種の並列CPUがあるため、これについて少し混乱していますか?

4

4 に答える 4

3

ロックのルールは簡単です。

別のスレッドによって同時にアクセスされる変数に書き込む場合は、操作の適切な順序付けが必要です (たとえば、ロックを介して)。

この単純なルールを使用すると、それぞれのケースを簡単に評価できます。

  1. 書き込み不要、同期不要
  2. 書き込み、同時アクセス、同期が必要
  3. 書き込み、同時アクセス、同期が必要

ロックしないとどうなりますか?

正式には、これは未定義の動作です。私たちにはわからないということです。ただし、可能な唯一の対応は、問題の範囲を把握するのに役立ちます。

マシン レベルでは、次のいずれかが発生する可能性があります。

  • 読み取りの場合: 古い値へのアクセス
  • 読み取りの場合: 部分的な値へのアクセス (見た時点で半分だけが更新されます)
  • 書き込みの場合: 最終的な値は値の寄せ集め (ビットレベル) です。

...そして、間違ったポインター/サイズを読み取るとクラッシュする可能性があることを忘れないでください。

コンパイラ レベルでは、コンパイラは、スレッドが単独でアクセスしているかのように最適化できます。この場合、次のことを意味します。

  • 「冗長な」読み取りの削除: に変換while (flag)if (flag) while (true)ます ...
  • 「未使用」書き込みの削除
  • ...

メモリ フェンスと明示的な同期命令 (mutex の使用によって導入される) の存在により、これらの最適化が妨げられます。

于 2013-08-02T12:56:20.280 に答える