关键字 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 ", data); // 可能 data 还没有更新! }
背景