详解volatile关键字和原子引用
本篇看一下Volatile关键字和原子引用。
上图就是JUC包结构,总共分成三块
(1)java.util.concurrent:并发包基础类,包括阻塞队列,线程池相关类,线程安全Map等。
(2)java.util.concurrent.atomic:原子引用相关类
(3)java.util.concurrent.locks:线程锁相关类
线程池技术在之前的讲解应该很清楚了,今天主要解析一个volatile关键字以及原子引用的相关类。这一篇文件涉及到JMM(java内存模型)的知识,之前也有讲解。
一、volatile
这个关键字,是JVM提供的轻量级的同步机制。可能在业务功能开发中很少涉及,但其是JUC包里面拥有重要地位的大哥。
首先看下理论:
(1)保证变量内存可见性:就是当前线程对某个volatile修饰的变量进行操作的话会及时通知到其它线程。比如现在的在线编辑文档,当某个人编辑了文档并保存之后,其他人会立马收到文档已被修改的通知。
(2)不保证原子性: 原子性的意思就是某个元素已经是最小的了,不可在被分割,比如现实中原子就是最小的粒子了,不可能再被分割。而映射到这边就是说某个操作不可在被分割成两个或多个操作,要么成功,要么失败。
(3)禁止指令重排:JVM为了获取最快的运行速度,会在底层一些没有先后性要求的指令进行一些指令重排的操作,在代码层面是一步一步执行,但在底层执行的时候并不是如此。比如JVM创建了一个对象有三步,创建实例对象、分配空间、将引用指向内存空间,但是第一步和第二步并没有什么关系,这个时候就可能会发生指令重排的操作。
代码示例:
(1)可见性代码验证:
当资源类变量a未加volatile关键字修饰的时候
当添加了volatile关键字修饰后:
(2)不保证原子性验证:
如果保证原子性,那么最后输出的结果应该是20000,而真实输出是19734,所以这可以 证明其不保证原子性。
JVM为了提供了可保证原子性的原子类。
二、原子类
下图就是原子类的结构图
先用AtomicInteger类是否可以保证原子性。不多说,上图片。
可以看到,用原子类AtomicInteger类是可以获取期望值的,也就是保证了原子性。
接下来看一下原子类底层是怎么样的。
上图可以看到,有三个变量,分别是value,valueOffset,unsafe。
(1)value:是volatile关键字修饰的,也就是说原子类底层也是volatile变量。
(2)valueOffset:当前变量的内存位移值。
(3)unsafe:下图可以看到,unsafe类里面都是native修饰的本地方法,是直接调用其他语言进行操作变量的。
看一下原子类的addAndGet方法为什么能实现原子性呢?
点进去会看到它调用了unsafe的getAndAddInt方法。
继续点下去会看到如下方法,里面有个compareAndSwap。
介绍一个compareAndSwap方法,简称CAS(比较并交换),其有三个值,内存值V,旧的预估值A,更新值B。只有当V和A相等的时候,才会将变量的的值修改为B,否则什么都不干。
可以看到,上述的getAndAddInt方法是个自旋锁的实现,一直调用getIntVolatile(也是本地方法)方法获取对象的最新值,获取之后就会调用CAS方法。
CAS:原称为Compare-And-Swap,比较并交换,是一条cpu的并发原语,它的功能是判断内存某个位置的值是否为预期值,如果是则更改为预期值,这个过程是原子的。
并发原语体现在调用unsafe的方法。原语是属于操作系统的范畴,原语的执行必须是联系的,也就是原子性,不会造成所谓的数据不一致的问题。(这个我也不是很懂,毕竟我不是科班出身的程序员,应该是要学操作系统才会明白)
(如果大厂面试的时候让你手写一个自旋锁,就把上述代码糊他脸上)
上述就是其保证原子性的方法,利用自旋锁和unsafe类。
说完原子类的底层,进行拓展一下:上述可以看到,原子类java只提供了基本类型的封装,例如AtomicInteger,AtomicLong等,但是工作中需要很多其他自定义的实体,也要保证原子性,该怎么办呢?
别慌,JVM还提供了原子引用类型AtomicReference,下图可见此类是一个泛型类。
下次会带大家看一下CAS导致的ABA问题。
=======================================================
我是Liusy,一个喜欢健身的程序员。
欢迎关注公众号【Liusy01】,一起交流Java技术及健身,获取更多干货。
详解volatile关键字和原子引用的更多相关文章
- 详解 volatile关键字 与 CAS算法
(请观看本人博文 -- <详解 多线程>) 目录 内存可见性问题 volatile关键字 CAS算法: 扩展 -- 乐观锁 与 悲观锁: 悲观锁: 乐观锁: 在讲解本篇博文的知识点之前,本 ...
- 详解volatile 关键字与内存可见性
先来看一个例子: public class VolatileTest { public static void main(String[] args) { T ...
- Java之static静态关键字详解|final关键字详解
前言 在Java语言中,static表示"静态"的意思,使用场景可以用来修饰成员变量和成员方法,当然也可以是静态代码块.static的主要作用在于创建独立于具体对象的域变量或者方法 ...
- 翻译「C++ Rvalue References Explained」C++右值引用详解 Part5:右值引用就是右值吗?
本文为第五部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...
- 翻译「C++ Rvalue References Explained」C++右值引用详解 Part3:右值引用
本文为第三部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/4220233.html. 右值引用 如果x是任意类型,那么x&&则被称作一个 ...
- 详解JNDI的lookup资源引用java:/comp/env
ENC的概念: The application component environment is referred to as the ENC, the enterprise naming c ...
- 详解JNDI的lookup资源引用 java:/comp/env
ENC的概念: The application component environment is referred to as the ENC, the enterprise naming c ...
- 详解php中函数的引用传递和返回 (附代码)
本篇文章带大家了解一下php的引用,详细介绍一下函数的引用传递和引用返回.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助.php的引用(就是在变量或者函数.对象等前面加上&符号 ...
- Java(2)详解注释&关键字&常量&变量&标识符
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201497.html 博客主页:https://www.cnblogs.com/testero ...
随机推荐
- Spring Boot系列(三):Spring Boot整合Mybatis源码解析
一.Mybatis回顾 1.MyBatis介绍 Mybatis是一个半ORM框架,它使用简单的 XML 或注解用于配置和原始映射,将接口和Java的POJOs(普通的Java 对象)映射成数据库中的记 ...
- 使用hexo+github搭建博客
https://blog.csdn.net/qq_36667170/article/details/105789610这一篇已经写得很详细了,下面的内容是我操作的时候遇到的问题及解决方法. 1.下载N ...
- Jmeter 常用函数(26)- 详解 __chooseRandom
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 从指定的范围里面取值 语法格式 ${_ ...
- Vue DevTools 安装应用
1.https: //github.com/vuejs/vue-devtools 从这上面下载Vue DevTools: 2.npm install(cnpm install) && ...
- 源码浅入浅出 Java ConcurrentHashMap
从源码的角度深入地分析了 ConcurrentHashMap 这个线程安全的 HashMap,希望能够给你一些帮助. 老读者就请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程 ...
- oracle的system登不了
(密码对的,密码错直接就是被拒了) 这个一直弹出改密码 但是改了点[确定],又说 oracle改system密码 [oracle@localhost ~]$ sqlplus / as sysdba S ...
- js动画和css3动画的区别
JS动画(逐帧动画) 首先,在js动画是逐帧动画,是在时间帧上逐帧绘制帧内容,由于是一帧一帧的话,所以他的可操作性很高,几乎可以完成任何你想要的动画形式.但是由于逐帧动画的帧序列内容不一样,会增加制作 ...
- Spring Security如何优雅的增加OAuth2协议授权模式
一.什么是OAuth2协议? OAuth 2.0 是一个关于授权的开放的网络协议,是目前最流行的授权机制. 数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令 ...
- Kubernetes K8S之资源控制器Daemonset详解
Kubernetes的资源控制器Daemonset详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS7.7 2C/ ...
- Linux安装doker
docker安装(centos) 官方文档:https://docs.docker.com/engine/install/centos/ 前提条件 内核系统3.10以上的centos7.可用 unam ...