volatile等

本文详细解释了volatile和synchronized的区别,并通过实例说明它们如何确保变量读写的一致性,强调volatile保证变量值在同一时间一致,而synchronized则确保了线程安全的读写操作。
volatile
和synchronized一起比较会好理解。同一个变量,什么都不用,各线程处理时,变量值在同一时间,可能是不同的;volatile能保证同一时间,变量值是一致的;synchronized能保证修改变量值是一个一个线程排队来的(比如同一时间,线程1和线程2都读取了变量i=1,没有问题,但是不用synchronized,就会同时修改i,如果是i=6,这样是没有问题的,因为不依赖任何东西,如果是i++,就非常有问题了,两个线程,++两次,应该i=3,由于没有synchronized,各搞各的,可能最后值为2)。

volatile保证读一致,synchronized保证读写一致。
volatile修饰变量,synchronized修改方法/代码块。

还有一点对理解很重要,java有主内存,就是说每个线程会把变量保存在线程局部,用了volatile就只会保存在共享。
### Volatile关键字的作用及用法 #### 一、Volatile的关键作用 1. **可见性** - 当一个线程修改了一个`volatile`变量的值时,新值会立即对其他线程可见[^1]。这意味着任何线程都不会因为本地缓存而读取到陈旧的数据。 2. **有序性** - 对于`volatile`变量的操作不会被编译器或处理器重排序[^4]。即,在程序中先发生的写操作一定会在线程间保持其发生顺序。 3. **防止优化** - 编译器会对代码进行各种优化以提高性能,但对于标记为`volatile`的变量,这些优化会被禁用[^2]。这样可以确保每次访问都直接从内存获取最新值而不是依赖寄存器或其他形式的缓存副本。 #### 二、不同语言下的实现细节对比 ##### Java 中的 `volatile` - 在Java中, 使用`volatile`主要解决的是多线程环境下的共享变量一致性问题[^1]。如果某个字段可能由多个线程同时更新,则应将其声明为`volatile`以便维持跨线程的一致性和及时传播最新的状态变化给所有观察者。 ```java public class Counter { public volatile int count = 0; public void increment() { this.count++; } } ``` 注意:虽然这里使用了`volatile`,但是由于复合赋值语句(`count++`)并非原子操作,因此仍可能存在竞态条件(race condition),需要进一步考虑同步机制如`synchronized` 或者更高级别的锁结构来保障安全性. ##### C/C++中的 `volatile` - 在C/C++里,`volatile`主要用于指示那些可能会被外部因素改变的对象(例如硬件中断)[^2]^。它并不像Java那样提供完整的内存屏障(memory barriers)功能;也就是说,尽管能阻止某些特定类型的指令重组(reordering),但它无法完全控制CPU级别上的乱序执行(out-of-order execution). 例子如下所示: ```cpp #include <iostream> using namespace std; class DeviceStatus{ private: bool status_; public: explicit DeviceStatus(bool s):status_(s){}; inline void setStatus(bool newS){ *(reinterpret_cast<volatile bool*>(&this->status_))=newS;//强制作为易失型处理 }; inline bool getStatus(){ return *(reinterpret_cast<const volatile bool*>(&this->status_)); }; }; int main(){ DeviceStatus ds(false); cout<<ds.getStatus()<<endl; ds.setStatus(true); cout<<ds.getStatus()<<endl; return 0; } ``` 在这个案例当中我们通过显式的转换使得成员函数能够正确对待内部标志位作为一个真正的波动量看待。 ##### 单片机开发中的应用[C] - 针对手持设备或者嵌入式系统的编程场景下,经常涉及到外设寄存器的状态监控以及实时响应等情况。此时利用好`volatile`可以帮助开发者避免因过度激进的编译选项而导致逻辑错误的发生[^3]. 示例片段: ```c #define LED_PIN (* (unsigned char *) 0x80) void toggleLed(void){ static unsigned char state = LOW ; LED_PIN =state ;//此处必须保证每次都实际输出至端口而非仅仅停留在局部计算层面 state ^= HIGH ^LOW ; } int main(){ while(1){ delay_ms(500); //假设存在这样一个延时子程序 toggleLed(); } } ``` 在这里如果没有加上`volatile`限定的话,很可能经过多次迭代之后发现LED灯并没有按预期闪烁的现象就是因为编译阶段做了不必要的简化所致。 --- ### 总结 综上所述可以看出无论是在哪种具体的上下文中运用到了`volatile`这一概念都是围绕着如何有效应对不可预测的变化展开讨论并采取相应措施加以防范的过程体现出来的共同特点就是强调即时反馈的重要性同时也提醒使用者要注意区分各自平台特性差异所带来的局限之处。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值