原创转载请注明出处: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/

Java中volatile如何保证long和double的原子性操作的更多相关文章

  1. java中volatile不能保证线程安全

    今天打了打代码研究了一下java的volatile关键字到底能不能保证线程安全,经过实践,volatile是不能保证线程安全的,它只是保证了数据的可见性,不会再缓存,每个线程都是从主存中读到的数据,而 ...

  2. Java中Volatile关键字详解

    一.基本概念 先补充一下概念:Java并发中的可见性与原子性 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值, ...

  3. java中volatile

    volatile用来修饰变量.Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 synchronized 块相比,volat ...

  4. java中volatile关键字的理解

    一.基本概念 Java 内存模型中的可见性.原子性和有序性.可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有 ...

  5. Java中Volatile关键字详解(转载)

    转载自:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是 ...

  6. Java中Volatile关键字详解 (转自郑州的文武)

    java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...

  7. 【转】java中volatile关键字的含义

    java中volatile关键字的含义   在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  8. 转:java中volatile关键字的含义

    转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  9. Java中Volatile的作用

    Java中Volatile的作用 看了几篇博客,发现没搞懂.可是简单来说,就是在我们的多线程开发中.我们用Volatile关键字来限定某个变量或者属性时,线程在每次使用变量的时候.都会读取变量改动后的 ...

随机推荐

  1. vue中v-model详解

    vue中经常使用到<input>和<textarea>这类表单元素,vue对于这些元素的数据绑定和我们以前经常用的jQuery有些区别.vue使用v-model实现这些标签数据 ...

  2. Linux重定向命令(stdout, stdin, stderr)

    ls -l /usr/bin > ls-output.txt 将输出结果重定向到 ls-output.txt 文件.注意:再次使用> ls-output.txt会默认覆盖源文件.如果要追加 ...

  3. NET Core+win10+Jenkins+Github持续集成

    本篇和上一篇NET Core+win10+Jenkins+Gogs+open ssh持续集成没什么区别,只不过源码库换成github. 这里有两点不一样的是: 获取的代码的凭证不用用户名和密码用sec ...

  4. HTTP协议-get请求与post请求的区别

    区别: 参数:get通过url进行传递:post放在request body中 长度:get请求在url的长度是有限制的:而post没有(其实这个限制是来自浏览器和web服务器对url的限制,并不是h ...

  5. 【C++11新特性】 C++11智能指针之weak_ptr

    如题,我们今天要讲的是C++11引入的三种智能指针中的最后一个:weak_ptr.在学习weak_ptr之前最好对shared_ptr有所了解.如果你还不知道shared_ptr是何物,可以看看我的另 ...

  6. Python3解leetcode Maximum SubarrayHouse Robber

    问题描述: You are a professional robber planning to rob houses along a street. Each house has a certain ...

  7. UVA 12012 Detection of Extraterrestrial(KMP求循环节)

    题目描述 E.T. Inc. employs Maryanna as alien signal researcher. To identify possible alien signals and b ...

  8. 【项目管理和构建】——Maven简介(一)

    在现实的企业中,以低成本.高效率.高质量的完成项目,不仅仅需要技术大牛,企业更加需要管理大牛,管理者只懂技术是远远不够的.当然,管理可以说有很多的方面,例如:对人员的管理,也有对项目的管理等等.如果你 ...

  9. 使用Excel表格的记录单功能轻松处理工作表中数据的方法

    使用Excel表格的记录单功能轻松处理工作表中数据的方法 记录单是将一条记录分别存储在同一行的几个单元格中,在同一列中分别存储所有记录的相似信息段.使用记录单功能可以轻松地对工作表中的数据进行查看.查 ...

  10. C# DotNetZip压缩单、多文件以及文件夹

    有些项目为了更好的用户体验,会把下载文件做成一个压缩的文件,直接下载,免得去一个个的点击下载文件.网上有很多压缩文件的方法,也有第三方的分装DLL文件,本文主要介绍DotNetZip压缩方法. Dot ...