この関数を考えてみましょう:
void foo(int * p)
{
// something
}
コンパイラは、p が指す値を他のスレッドが変更しないと想定できますか? それとも、この値をいつでも変更できるかのように振る舞う必要がありますか?
void bar(volatile int * p)
{
}
そうでない場合、volatile
キーワードは役に立ちますか? GOTW #69は、volatile
キーワードはほとんど常にコンパイラによって無視されると述べています。
編集:どうやら「コンパイラが想定する」というフレーズに誤解があるようです。これを明確にしましょう:
- コンパイラーがそうであると想定する場合、最初に読み取られたときに の値をレジスターに入れ、
*p
p が範囲外になるまでそれを使用できます。その時点で、*p
そのメモリアドレスに の値を書き込む必要があります。 - コンパイラがそのように想定していない場合、が読み込まれるたび
*p
に、コンパイラはその値をメモリからフェッチする必要があります。これは、他のスレッドが値を変更した可能性があるためです。が変更されるたび*p
に、コンパイラはそれをメモリに書き込んで、他のスレッドが読み取れるようにする必要があります