volatileキーワードは、変数がコンパイラにとって予期しない方法で変更される可能性があることをコンパイラに伝え(たとえば、ハードウェア、別のスレッド、または割り込みハンドラによって)、その値をキャッシュしたり最適化したりすることを禁止します。
使用される場所:
volatileは原子性や同期を保証しません!)。volatile int flag = 0; void handler() { flag = 1; // 割り込みハンドラ } void loop() { while (!flag) { // イベントを待つ } // ... }
volatileがない場合、コンパイラはループを無限に置き換えることができ(メモリからflagを読み込まない)、volatileを使用すると変数は毎回メモリから読み込まれます。
スレッド間の情報交換を正しく行うためにvolatileを使用するだけで十分ですか?
一般的な誤解は、volatileがスレッド間のメモリ同期を保証し、操作を原子性にすると思うことです。
正しい回答:
volatileはマルチスレッド環境におけるデータ競合から保護せず、メモリバリアを提供しません:これはコンパイラに対しアクセスを最適化しないように指示するだけです。正確性を保証するためには、必ず同期プリミティブ(mutex、atomic操作など)を使用する必要があります。
// これは安全ではありません! volatile int ready = 0; void thread1() { data = 123; // データを書き込む ready = 1; // 別のスレッドに通知 } void thread2() { while (!ready); // イベントを待つ printf("data = %d\n", data); // データがまだ更新されていない可能性があります! }
歴史