今天被人问到volatile能不能保证并发安全?

呵,这能难倒我?

上代码:

//电脑太好,100线程起步~
public class ThreadTest {
private static volatile int num = 0; public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
num++;
System.out.println(num);
}
}).start(); Thread.sleep(500);
System.out.println(num);
}
}
输出结果:
  9998
  9998

分析:

  100个线程对volatilei修饰的num++,会被编译成以下三步:
   1.获取i的值;2.执行i+1;3.将结果赋值给i。
  volatile只能保证可见性,并不能保证原子性。

结论:
  volatile只能保证这3步在编译后指令不会被重新排序,并不能保证并发数据安全。建议搭配上synchronized或其他Lock锁使用。

最新文章

  1. android内部培训视频_第五节(1)_OA实战之登录界面
  2. WebService -- Java 实现之 CXF ( 使用Spring添加拦截器)
  3. oracle 序列、视图、索引
  4. Bzoj索引
  5. Git Day03,GitHub 1st
  6. paip.utf-8,unicode编码的本质输出unicode文件原理 python
  7. 最大似然估计(MLE)和最大后验概率(MAP)
  8. 为checkboxSelectionModel赋值
  9. CSS 元素垂直居中的 6种方法
  10. Nginx 配置指令的执行顺序(五)
  11. cad实时平移快捷键
  12. C++_基础_类和对象2
  13. Python-01 学习第一节
  14. vue md5
  15. [Android] Android GreenDao 保存 JavaBean 或者List &lt;JavaBean&gt;类型数据
  16. python-文字转语音-pyttsx3
  17. Testlink1.9.17使用方法(第十一章 其他易用性功能)
  18. Kolmogorov–Smirnov test(KS)
  19. Linux中环境变量文件
  20. 34.纯 CSS 创作在文本前后穿梭的边框

热门文章

  1. 【随便写写】印象笔记,WordPress,CSDN 等 写博客的不同
  2. .NET测试断言工具Shouldly
  3. web前端学习笔记(python)(一)
  4. 利用Visual Studio调试JavaScript脚本
  5. Java 程序员每天都在做什么?
  6. 鸿蒙的js开发模式19:鸿蒙手机下载python服务器端文件的实现
  7. Java 集合框架 02
  8. TestLink测试用例管理工具使用说明
  9. rest framework parsers
  10. 前端学习 node 快速入门 系列 —— 模块(module)