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++
- 获取数字的最后一位 2022-01-01
- java.lang.IllegalStateException:Bean 名称“类别"的 BindingResult 和普通目标对象都不能用作请求属性 2022-01-01
- 将 Java Swing 桌面应用程序国际化的最佳实践是什么? 2022-01-01
- 未找到/usr/local/lib 中的库 2022-01-01
- 如何指定 CORS 的响应标头? 2022-01-01
- 如何使 JFrame 背景和 JPanel 透明且仅显示图像 2022-01-01
- 在 Java 中,如何将 String 转换为 char 或将 char 转换 2022-01-01
- 转换 ldap 日期 2022-01-01
- GC_FOR_ALLOC 是否更“严重"?在调查内存使用情况时? 2022-01-01
- Eclipse 的最佳 XML 编辑器 2022-01-01