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++
基础教程推荐
- 如何对 HashSet 进行排序? 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01