3

この関数を考えてみましょう:

void foo(int * p)
{
   // something
}

コンパイラは、p が指す値を他のスレッドが変更しないと想定できますか? それとも、この値をいつでも変更できるかのように振る舞う必要がありますか?

void bar(volatile int * p)
{
}

そうでない場合、volatileキーワードは役に立ちますか? GOTW #69は、volatileキーワードはほとんど常にコンパイラによって無視されると述べています。

編集:どうやら「コンパイラが想定する」というフレーズに誤解があるようです。これを明確にしましょう:

  • コンパイラーがそうであると想定する場合、最初に読み取られたときに の値をレジスターに入れ、*p p が範囲外になるまでそれを使用できます。その時点で、*pそのメモリアドレスに の値を書き込む必要があります。
  • コンパイラがそのように想定していない場合、が読み込まれるたび*pに、コンパイラはその値をメモリからフェッチする必要があります。これは、他のスレッドが値を変更した可能性があるためです。が変更されるたび*pに、コンパイラはそれをメモリに書き込んで、他のスレッドが読み取れるようにする必要があります
4

5 に答える 5

5

コンパイラーはその仮定を行うことができず、プログラマーもできません。volatile キーワードだけでは、同時アクセスを防ぐことはできません。

于 2012-09-10T19:38:10.650 に答える
3

コンパイラは、 が指す値を他のスレッドが変更しないと想定することがpできます。つまり、コードがこれに依存していないこと、または競合状態を回避するための適切な同期メカニズムがあることを確認する必要があります。言い換えれば、コンパイラは仮定を行い、その仮定は間違っている可能性があります。

このvolatileキーワードは、ここではほとんど関連性がありません。

于 2012-09-10T19:38:24.920 に答える
2

ルールは次のとおりです。あるスレッドがデータの場所に書き込むと同時に、別のスレッドが同じ場所からの読み取りまたは同じ場所への書き込みを行う場合、プログラムにはデータ競合があり、プログラムの動作は定義されていません。行間を読み取ると、コンパイラ他のスレッドがデータに書き込んでいないと想定します。データの競合を防ぐのはあなたの仕事です。そして、いいえ、それにvolatileは影響しません。

于 2012-09-10T19:56:52.520 に答える
1

各スレッドは、そのスレッドで発生した呼び出しを表すパラメーターの独自のコピーを取得します。'p'の値は、実際にすべてが同じものを指している場合にのみ共有されます。別のスレッドで「p」に割り当てても、同じ変数ではないため、このスレッドの「p」には影響しません。

'p'が指しているのは、まったく別の話です。これは単にメモリの領域です。他のスレッドがそれにアクセスできる場合、それらはそれにアクセスでき、いつでもそれに書き込むことができます。このように共有されているものを保護する唯一の方法は、ミューテックスを使用することです。

于 2012-09-10T19:54:47.920 に答える
1

そうでない場合、volatile キーワードは役に立ちますか?

スレッドではなく、コンパイラ (つまり、最適化なし) によって無視されます。

于 2012-09-10T19:39:52.583 に答える