Java parallel volatile i++(Java并行易失性I++)
问题描述
我有一个全局变量
volatile i = 0;
和两个线程。每个组件执行以下操作:
i++;
System.out.print(i);
我收到以下组合。12、21和22。
我理解为什么我不能得到11(易失性不允许缓存I)和我也理解12和22。
我不明白的是,怎么可能得到21?
获得这种组合的唯一可能方法是,稍后打印的线程必须是第一个将i
从0递增到1,然后缓存i==1
。然后另一个线程将i
从1递增到2,然后打印2。然后第一个线程打印缓存的i==1
。但我认为volatile
不允许缓存。
编辑:在运行代码10,000次之后,我得到了11次。将volatile
添加到i
根本不会更改可能的组合。
markspace是对的:Volatile禁止i
缓存,但i++
不是原子的。这意味着i
在递增期间仍会在寄存器中得到某种程度上的"缓存"。
r1 = i
//if i changes here r1 does not change
r1 = r1 + 1
i = r1
这就是11仍然有可能的原因。21是因为PrintStream未同步(请参阅Karol Dowbecki的答案)
推荐答案
不幸的是++
不是原子操作。尽管volatile
不允许缓存,但允许JVM作为单独的操作进行读取、递增和写入。因此,你试图实现的概念是行不通的。您需要使用synchronized
作为其互斥锁,或者使用类似于AtomicInteger
的命令来提供原子增量操作。
这篇关于Java并行易失性I++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Java并行易失性I++


基础教程推荐
- 从 python 访问 JVM 2022-01-01
- 在 Java 中创建日期的正确方法是什么? 2022-01-01
- Java 实例变量在两个语句中声明和初始化 2022-01-01
- 如何在 JFrame 中覆盖 windowsClosing 事件 2022-01-01
- 验证是否调用了所有 getter 方法 2022-01-01
- 如何在 Spring @Value 注解中正确指定默认值? 2022-01-01
- 多个组件的复杂布局 2022-01-01
- 不推荐使用 Api 注释的描述 2022-01-01
- Java Swing计时器未清除 2022-01-01
- 大摇大摆的枚举 2022-01-01