大家好,欢迎关注我的公众号码猿bug,需要资料的话可以加我微信好友。

再谈volatile关键字之前,首先必须聊聊JMM内存模型!

JMM主要的特性:可见性、原子性,顺序性

Java 虚拟机规范试图定义一种 Java 内存模型(JMM),来屏蔽掉各种硬件和操作系统的内存访问差异,让 Java 程序在各种平台上都能达到一致的内存访问效果。简单来说,由于 CPU 执行指令的速度是很快的,但是内存访问的速度就慢了很多,相差的不是一个数量级,所以搞处理器的那群大佬们又在 CPU 里加了好几层高速缓存。在 Java 内存模型里,对上述的优化又进行了一波抽象。JMM 规定所有变量都是存在主存中的,类似于上面提到的普通内存,每个线程又包含自己的工作内存,方便理解就可以看成 CPU 上的寄存器或者高速缓存。所以线程的操作都是以工作内存为主,它们只能访问自己的工作内存,且工作前后都要把值在同步回主内存。

网上找的一些定义:

简单描述如下:

  • 主存存放线程需要操作的变量,但线程并不直接操作主存。
  • 每个线程读取主存变量都是先拷贝一份到工作内存中,不同线程工作内存互不干扰。
  • 线程修改了工作内存后,再写回主存中。
  • 每次从主存读写的过程都需要经过原子性操作。

简单知道了java的内存模型,那开始聊聊volatile关键字。volatile关键字有三大特性:

①可见性

②不保证原子性

③禁止指令重排

首先要知道volatile是java虚拟机提供的轻量级的同步机制,volatile的可见性是由jvm发送一条lock前缀的汇编指令实现的。volatile关键字是修饰成员变量的,也就是说,如果一个成员变量加了volatile关键字,就会告诉编译器和jvm的内存模型,这个变量是对所有线程共享的,可见性每次JVM都会读取最新写入的值并使其最新值在所有的cpu可见。volatile可以保证线程的可见性并且提供了一定的顺序性,但是无法保证原子性。在JVM底层volatile是采用内存屏障来实现的。使用了volatile关键字就好像是线程直接操作了主内存。

为什么不能保证原子性呢?

在我们的程序中,即使加了volatile也不能保证原子性,有一种粗暴的解决办法,就是加我们的synchronized同步锁,但是这种锁太重了。简单画个图演示为什么不能保证原子性。

在程序中的i++操作,是不能保证原子性的.

那原子性和可见性不是就冲突了吗?不冲突

因为volatile 的可见性只能对应l原子性, a=1是原子性,而a++实际上是a=a+1 是非原子性的,所以会导致你说的情况,这时候就要引入同步,强制将a++转化为原子性。

那除了synchronized还有其他解决办法吗?

那就是大名鼎鼎的JUC包下的AtomicInteger,写一小段程序说明:

AtomicInteger 

那为什么用AtomicInteger就能保证原子性呢?因为他的底层是CAS,接下来就要说说什么是cas了。

cas是compare and set的缩写,比较并交换,unsafe是cas的核心类,cas的底层是靠的unsafe类来保证原子性的,unsafe是jvm下的rt.jar的运行jar包里面。

跟进源代码可以看见这段代码:

public final int getAndIncrement(){return unsafe.getAndAddInt(this,1);//这个1是值的valueoffset:内存地址偏移量
}

还靠的是一段do while循环,顾名思义,又叫自旋锁

这时候就应该思考,为什么在没有加锁的情况下,还能保证线程安全呢?

①因为atomicInteger借助了UnSafe提供的CAS操作能够保证数据更新的时候是线程安全的,那么为什么借助了unsafe就能保证线程安全呢?以下总结出自我的笔记

因为cas并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用Unsafe类中的CAS方法,JVM会帮我们实现汇编指令,这是一种完全依赖的硬件功能。通过他实现了原子操作。并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题,保证了线程安全。

下一篇文章中会继续讨论CAS的缺点以及volatile的应用场景。技术小白一枚,希望各位大佬指出错误,互相讨论。

setnx是原子操作吗_谈谈Volatile关键字?为什么不能保证原子性?用什么可以替代?为什么?...相关推荐

  1. 两个原子操作组合到一块不一定是能保证原子性

    1.两个原子操作组合到一块不一定是能保证原子性 ConcurrentLinkedQueue AtomicInteger  两个类都为线程安全的类,但是组合起来并不能保证原子性: public stat ...

  2. volatile 关键字是如何保证可见性的?

    我们可以使用[hsdis]这个工具,来查看前面演示的这段代码的汇编指令,具体的使用请查看使用说明文档 在运行的代码中,设置jvm参数如下 [-server -Xcomp -XX:+UnlockDiag ...

  3. 双重检查锁单例模式为什么要用volatile关键字?

    前言 从Java内存模型出发,结合并发编程中的原子性.可见性.有序性三个角度分析volatile所起的作用,并从汇编角度大致说了volatile的原理,说明了该关键字的应用场景:在这补充一点,分析下v ...

  4. 一文读懂Java内存模型(JMM)及volatile关键字

    点赞再看,养成习惯,公众号搜一搜[一角钱技术]关注更多原创技术文章. 本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章. 前言 并发编程从操作系统底层工作的整 ...

  5. java多线程中volatile关键字

    一:计算机中的内存模型 计算机中指令都通过CPU去执行,执行执行的时候一般都会涉及到读写,我们都知道CUP的计算速度是很快的,如果都把数据放到我们的主存中则会造成CPU每执行一条指令都要等待的问题,这 ...

  6. volatile关键字——保证并发编程中的可见性、有序性

    文章目录 一.缓存一致性问题 二.并发编程中的三个概念 三.Java线程内存模型 1.原子性 2.可见性 3.有序性 四.深入剖析volatile关键字 1.volatile关键字的两层语义 2.vo ...

  7. java中volatile关键字---学习笔记

    volatile关键字的作用 在java内存模型中,线程之间共享堆内存(对应主内存),但又各自拥有自己的本地内存--栈内存,线程的栈内存中缓存有共享变量的副本,但如果是被volatile修饰的变量,线 ...

  8. java:彻底搞懂volatile关键字

    对于volatile这个关键字,相信很多朋友都听说过,甚至使用过,这个关键字虽然字面上理解起来比较简单,但是要用好起来却不是一件容易的事. 这篇文章将从多个方面来讲解volatile,让你对它更加理解 ...

  9. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

最新文章

  1. GMQ集团推出全球创新型金融衍生品交易平台
  2. [BZOJ1419] Red is good(期望DP)
  3. [C语言] va_start和va_end详解
  4. idea 新建的java项目没发run_IntelliJ IDEA创建普通的Java 项目及创建 Java 文件并运行的教程...
  5. [react] create-react-app创建新运用怎么解决卡的问题?
  6. 提高篇 第一部分 基础算法 第4章 广搜的优化技巧
  7. 用SQL语句实现:当A列大于B列时选择A列否则选择B列,当B列大于C列时选择B列否则选择C列。...
  8. DQL——数据查询语言
  9. Android app是如何杀掉的
  10. ENSP-----华为USG6000防火墙
  11. 帝国cms !--list.var1--,!--list.var2--的终极用法
  12. 最值得入手的五款骨传导耳机,几款高畅销的骨传导耳机
  13. 迅速提高产品用户体验、交互、界面设计的几个绝妙方法
  14. ceph radosgw-admin的操作
  15. 【DevOps】我们忽视了Daily Build(每日构建)吗?
  16. ENVI中使用水体指数法NDWI提取水体
  17. SEO优化_网站诊断分析方法
  18. 使用Python和OpenCV标记超级像素的炫彩度
  19. C语言实现中文模糊查询
  20. 马云连续三年蝉联中国首富

热门文章

  1. .NET Task揭秘(一)
  2. 关于全局ID,雪花(snowflake)算法的说明
  3. IIS负载均衡-Application Request Route详解第三篇:使用ARR进行Http请求的负载均衡
  4. spark java 逻辑回归_逻辑回归分类技术分享,使用Java和Spark区分垃圾邮件
  5. java jtable defaulttablemodel_java – JTable和DefaultTableModel
  6. 1、RN跨平台开发——环境搭建
  7. ArcGIS10.8中如何获取线状、面状数据的折点,并计算折点坐标?
  8. 回溯算法之购物车(0-1 背包问题)
  9. Android之如何解决ScrollView起始位置不是最顶部的解决办法
  10. Android之View基础总结(View的事件体系一)