对Volatile的理解

对Volatile的理解    
很多人对Volatile都不太了解,其实Volatile是由于编译器优化所造成的一个Bug而引入的关键字.

         int a = 10;
         int b = a;
         int c = a;

        
理论上来讲每次使用a的时候都应该从a的地址来读取变量值,但是这存在一个效率问题,就是每次使用a都要去内存中取变量值,然后再通过系统总线传到CPU处理,这样开销会很大.所以那些编译器优化者故作聪明,把a读进CPU的cache里,像上面的代码,假如a在赋值期间没有被改变,就直接从CPU的cache里取a的副本来进行赋值.但是bug也显而易见,当a在赋给b之后,可能a已经被另一个线程改变而重新写回了内存,但这个线程并不知道,依旧按照原来的计划从CPU的cache里读a的副本进来赋值给c,结果不幸发生了.

        于是编译器的开发者为了补救这一bug,提供了一个Volatile让开发人员为他们的过失埋单,或者说提供给开发人员了一个选择效率的权利.当变量加上了Volatile时,编译器就老老实实的每次都从内存中读取这个变量值,否则就还按照优化的方案从cache里读.


volatile的本意是一般有两种说法--1.“暂态的”;2.“易变的”.

这两种说法都有可行.但是究竟volatile是什么意思,现举例说明(以Keil-c与a51为例
例子来自Keil
FQA),看完例子后你应该明白volatile的意思了,如果还不明白,那只好
再看一遍了.

转载于:https://www.cnblogs.com/tureno/articles/2828171.html

### ### 深入探讨 `volatile` 关键字的含义与使用场景 #### 1. **`volatile` 的核心意义** `volatile` 是一种特殊的修饰符,用于告知编译器该变量可能会被多个线程或其他外部因素修改。因此,每次访问此变量时都必须直接从内存中读取最新值,而非依赖寄存器或缓存中的旧值[^1]。 在 Java 和 C++ 中,`volatile` 都具有类似的用途,但在实现细节上有显著差异。以下是两者的具体解释: --- #### 2. **Java 中的 `volatile`** ##### (1)**主要功能** - **可见性**: 当一个线程更新了一个 `volatile` 变量的值时,其他线程能够立即感知到变化。这是由于 JVM 确保了对该变量的所有写操作都会刷新回主内存,并且所有读操作都将重新加载自主内存[^3]。 - **有序性**: Java 的 `volatile` 提供了一种较弱的同步机制,它通过 Acquire 和 Release 语义防止某些特定类型的指令重排序。例如: - 写操作前发生的动作不会被重排到写操作之后。 - 读操作后发生的动作不会被重排到读操作之前。 ##### (2)**典型应用场景** - 多线程环境下的标志位通知:当一个线程需要向另一个线程发送信号时,可以通过设置 `volatile` 标志位完成通信。例如: ```java public class MyThread extends Thread { private volatile boolean flag = false; public void run() { while (!flag) { // 执行任务... } System.out.println("线程停止"); } public void stopThread() { this.flag = true; } public boolean isFlag() { return flag; } } ``` 在此例子中,`flag` 被标记为 `volatile`,以确保主线程对其的修改能及时反映在线程内部的状态判断逻辑中[^4]。 --- #### 3. **C++ 中的 `volatile`** ##### (1)**主要功能** - 在 C++ 中,`volatile` 主要用于指示编译器不要对涉及该变量的操作进行优化,尤其是硬件中断或并发上下文中可能随时改变的变量[^1]。 - 不同于 Java,C++ 的 `volatile` 并不隐含任何关于原子性和多线程安全性的保障。这意味着即使将某变量声明为 `volatile`,也不能阻止 CPU 或编译器对其进行指令重排序[^5]。 ##### (2)**典型应用场景** - 访问硬件寄存器:如果程序需要直接操控设备寄存器,则应将其视为 `volatile` 类型,因为这些值可能由外设实时更新。 ```cpp volatile uint8_t* port_register = reinterpret_cast<volatile uint8_t*>(0x12345678); void togglePin() { *port_register ^= 0b00000001; // 切换最低有效位 } ``` - 实现简单的忙等待循环(Busy Waiting Loop),尤其是在嵌入式系统中: ```cpp volatile bool taskCompleted = false; while (!taskCompleted) { // 等待直到任务完成 } // 继续执行后续代码 ``` 注意:这种做法效率较低,仅适用于特殊场合;推荐优先考虑条件变量等高级同步工具[^5]。 --- #### 4. **两者之间的区别总结** | 特性 | Java (`volatile`) | C++ (`volatile`) | |--------------------|-------------------------------------------|---------------------------------------| | 是否支持多线程 | 支持 | 不支持 | | 是否防止单一变量内的重排序 | 是 | 否 | | 是否保证跨变量间的顺序一致性 | 是(借助Acquire/Release语义) | 否 | 由此可见,尽管名称相同,但二者的设计目标存在本质差别——前者专注于解决复杂的并发问题,后者则更多关注低级系统的交互需求。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值