Java|面试官问我什么是JMM( 三 )
内心:这可以重头戏呀 , 可不能出岔子~
很多并发编程都使用了volatile关键字 , 主要的作用包括两点:
- 保证线程间变量的可见性 。
- 禁止CPU进行指令重排序 。
volatile修饰的变量 , 当一个线程改变了该变量的值 , 其他线程是立即可见的 。 普通变量则需要重新读取才能获得最新值 。
volatile保证可见性的流程大概就是这个一个过程:
volatile一定能保证线程安全吗
先说结论吧 , volatile不能一定能保证线程安全 。
怎么证明呢 , 我们看下面一段代码的运行结果就知道了:
/**
* @author Ye Hongzhi 公众号:java技术爱好者
**/public class VolatileTest extends Thread {
private static volatile int count = 0;
public static void main(String[
args) throws Exception {
Vector<Thread> threads = new Vector<>();
for (int i = 0; i < 100; i++) {
VolatileTest thread = new VolatileTest();
threads.add(thread);
thread.start();
//等待子线程全部完成
for (Thread thread : threads) {
thread.join();
//输出结果 , 正确结果应该是1000 , 实际却是984
System.out.println(count);//984
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try { //休眠500毫秒
Thread.sleep(500);
catch (Exception e) {
e.printStackTrace();
count++;
为什么volatile不能保证线程安全?
很简单呀 , 可见性不能保证操作的原子性 , 前面说过了count++不是原子性操作 , 会当做三步 , 先读取count的值 , 然后+1 , 最后赋值回去count变量 。 需要保证线程安全的话 , 需要使用synchronized关键字或者lock锁 , 给count++这段代码上锁:
private static synchronized void add() {
count++;
禁止指令重排序
首先要讲一下as-if-serial语义 , 不管怎么重排序 , (单线程)程序的执行结果不能被改变 。
推荐阅读
- Java|淘宝商家要小心了!取消的“中差评”体系又回来啦!
- javascript|游戏开发之旅-JavaScript重新介绍
- Java|java多线程并发小demo
- Java|java程序猿如何才能走远,怎么做自己的职业规划
- 蚂蚁花呗|血亏!阿里P8轻易把总结了近一年的java高级特性笔记送人了
- jvm|清纯小学妹连续被三个大汉硬怼:JVM学成这样,还敢来面试?
- 百度|Java高级进阶多线程学习之路(七)ThreadLocal
- javascript|家里宽带是300M的,但是实际测速才2M应该这样维权。
- 社交|十一国庆过后,秋招Java岗,陆续收到字节/招银等offer
- Java|Java面试之基础问题答案口述整理