原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11426473.html

关键字volatile的主要作用是使变量在多个线程间可见,但无法保证原子性,对于多个线程访问同一个实例变量需要加锁进行同步。

 package org.fool.java.concurrent.volatiletest;  

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class VolatileTest1 { private static volatile int count = 0; private static void addCount() {
for (int i = 0; i < 100; i++) {
count++;
} System.out.println(Thread.currentThread().getName() + " count = " + count);
} public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 100; i++) {
executor.execute(new Runnable() {
@Override
public void run() {
VolatileTest1.addCount();
}
});
} executor.shutdown();
}
}

Note:

addCount()方法没有加synchronized

Console Output

预期结果应该是10000,尽管count被volatile修饰,保证了可见性,但是count++并不是一个原子性操作,它被拆分为load、use、assign三步,而这三步在多线程环境中,use和assgin是多次出现的,但这操作是非原子性的,也就是在read和load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,也就是私有内存和公有内存中的变量不同步,所以计算出来的值和预期不一样,就产生了线程安全的问题,所以需要用synchronized进行加锁同步

addCount()方法用synchronized进行加锁同步

Console Output

结果10000与预期一致

所以volatile只能保证可见性不能保证原子性,但用volatile修饰long和double可以保证其操作原子性

所以从Oracle Java Spec里面可以看到:

  • 对于64位的long和double,如果没有被volatile修饰,那么对其操作可以不是原子的。在操作的时候,可以分成两步,每次对32位操作。
  • 如果使用volatile修饰long和double,那么其读写都是原子操作
  • 对于64位的引用地址的读写,都是原子操作
  • 在实现JVM时,可以自由选择是否把读写long和double作为原子操作
  • 推荐JVM实现为原子操作

Reference

http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7

http://www.cnblogs.com/louiswong/p/5951895.html

http://ifeve.com/volatile/

http://www.infoq.com/cn/articles/java-memory-model-4/

最新文章

  1. angular学习笔记(二十八-附1)-$resource中的资源的方法
  2. Java设计模式(一) 简单工厂模式不简单
  3. (分享)FreeVideo1.6.1 VIP视频播放器(支持下载)
  4. Cloud Design Patterns Book Reading(undone)
  5. Raspberry Pi 3 --- Kernel Building and Run in A New Version Kernal
  6. The include feature of SQL Server Index
  7. C 简易基础开发框架 - simple c
  8. csharp excel interop programming
  9. uublog在线测试demo
  10. UpdatePanel和jQuery不兼容
  11. CSS selectors for Selenium with example,selenium IDE
  12. ORA-12545: Connect failed because target host or object does not exist
  13. Linq to sql 结
  14. URL中文参数乱码的一个解决办法
  15. Microsoft Visual Studio 2012正式版官方下载
  16. 阿里云负载均衡SLB的文件上传下载问题解决
  17. python3基础(一)
  18. js/jquery遇到的坑总结
  19. 《c#图解教程》
  20. 《机器学习实战(基于scikit-learn和TensorFlow)》第四章内容的学习心得

热门文章

  1. Spring---数据缓存Cache
  2. error和exception的不同与相同
  3. php ltrim()函数 语法
  4. JS中数据结构之栈
  5. Ant Design(ui框架)
  6. [杂题]:group(状压DP+轮廓线)
  7. 前端每日实战:18# 视频演示如何用纯 CSS 创作 404 文字变形为 NON 文字的交互特效
  8. linux下使用lftp的小结
  9. 洛谷P1219 八皇后
  10. EasyUI 的日期控件单击文本框显示日历