[java] volatile关键字对while循环条件提升问题补充

在java并发编程中,代码如下:
1 volatile boolean asleep;
2 ...
3 while(!asleep){
4 countSomeSheep();
5 }
如果此处忘记将asleep变量设置为volatile类型, 那么server模式运行的jvm会将asleep的判端条件提升到循环体外部,这将导致无限循环.单是client模式下的jvm并不会这么做.
关于如何以server模式启动jvm: 启动时,指定 -server参数即可.
 
 
 
-- 笔记出处: java并发编程实战
 

转载于:https://www.cnblogs.com/duenboa/p/6665258.html

### Java 中 `volatile` 关键字的作用 #### 可见性保障 当一个字段被声明为 `volatile` 后,它会确保该字段的修改对于所有线程都是立即可见的。这意味着一旦某个线程更新了一个 `volatile` 字段的值,这个新值将会立刻对其他线程可用,从而防止了由于缓存一致性问题而导致的数据不同步现象[^2]。 ```java public class VolatileExample { private volatile boolean isShutdown = false; public void shutdown() { isShutdown = true; } public void doWork() { while (!isShutdown) { // 执行工作... } } } ``` 在这个例子中,如果没有 `volatile` 修饰符,则可能存在一个问题:即使调用了 `shutdown()` 方法并设定了 `isShutdown=true`,但由于编译器优化或处理器指令重排序的原因,在某些情况下,另一个正在运行的工作线程可能看不到最新的 `isShutdown` 值变化而继续循环下去。通过加上 `volatile`,就可以解决这个问题。 #### 防止指令重排序 除了提供可见性的保证外,`volatile` 还能阻止编译器和CPU为了提高性能而进行不必要的指令重排序操作。这有助于保持程序逻辑的一致性和预期行为[^1]。 考虑下面的例子: ```java class Example { volatile int a = 0; volatile boolean ready = false; public void writerThread() { a = 5; // 语句1 ready = true; // 语句2 } public void readerThread() { while (!ready) { // 语句3 Thread.yield(); } System.out.println(a); // 语句4 } } ``` 这里定义了两个 `volatile` 的成员变量 `a` 和 `ready`。在 `writerThread` 方法里先设置整数 `a=5` ,再把布尔标志位 `ready` 设定为真;而在 `readerThread` 方法里面则不断轮询直到发现 `ready==true` 。因为有了 `volatile` 的存在,所以可以确信当 `ready` 被置成真的时候,之前发生的赋值动作(即 `a=5`)也已经被完成了,并且其结果已经传播给了所有的观察者线程。 #### 不保证原子性 需要注意的是,虽然 `volatile` 提供了一定程度上的同步机制,但它并不足以实现复杂的多线程安全的操作。特别是涉及到复合操作的时候——比如自增运算 (`i++`) 或者读取后再写回新的数值——此时仍然需要借助更高级别的锁或者其他形式的显式同步来保护数据完整性[^3]。 例如这段代码展示了如何利用 AtomicInteger 来替代普通的 int 类型以获得更好的线程安全性: ```java import java.util.concurrent.atomic.AtomicInteger; public class SafeCounter { private final AtomicInteger counter = new AtomicInteger(); public void increment() { counter.incrementAndGet(); } public int get() { return counter.get(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值