深入理解Atomic原子类
Atomic是基于unsafe类和自旋操作实现的,下面以AtomicInteger类为例进行讲解。
要理解Atomic得先了解CAS
CAS
CAS全程Compare And Swap ,是条并发原语,功能是判断内存中某个值是否与预期值相等,相等就用新值更新旧值,否则不更新。
Java中CAS是基于unsafe类实现的,所有的unsafe类中的方法都是native类修饰的,直接调用操作系统底层资源执行响应的任务。
unsafe.compareAndSwapInt(this, valueOffset, expect, update);
这是一条调用unsafe类中的compareAndSwapInt的方法,this表示当前对象,valueoffset表示当前对象的偏移地址,expect表示预期值
update表示更新值。作用是如果预期值和该对象偏移地址中的值一样,就用更新值更新偏移地址中的值。
AtomicInteger类初始化
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset; static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
} private volatile int value;
上述代码是AtomicInteger类的默认参数初始化过程。其中value就是我们想要进行操作的那个值。加上volatile是为了
保证修改该值后立马被其他线程感知到。
刚开始实例化unsafe类,这没什么好说的,因为AtomicInteger类中方法都是通过unsafe类中方法来操作的。在静态代码块中通过
unsafe.objectFieldOffset方法获取value值的偏移量。也可以说是引用地址,以后通过该地址就可以随时获取value值和更改value值
AtomicInteger中方法的执行流程
这里我们以常用的getAndIncrement方法为例
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
可以看到,该方法是调用unsafe类中的getAndAddInt方法,继续跟踪该方法,进入unsafe类源代码中
可以看到,调用unsafe类中getIntVolatile方法,方法参数var1为传入的对象,即上述的AtomicInteger类的对象
var2为偏移地址,该方法的作用是通过该对象的偏移地址找到值,也就是找到上文的value值。(注意!这里已经
不是在AtomicInteger类源代码中了而是进入了Unsafe类源代码中,所以这里的this.getIntVolatile是unsafe类中的
getIntVolatile方法,该方法不是在AtomicInteger类中!)获取到目前的value值后调用compareAndSwapInt方法,
使用获取到的value值和当前当前对象地址偏移量中的值进行比较,如果相同就更新值,并且退出循环,否则就继续
进入循环获取该偏移地址中的最新值。为什么这里会导致使用var5 = getIntVolatile获取偏移地址中的值后后面compareAndSwapInt
方法var5又会出现不等于偏移量地址上的值呢?按道理来说两次获取同一个偏移地址上的值是肯定会相同的,但是这里我们
考虑多线程的情况下,当两个线程同时获取当前偏移地址上的值,由于compareAndSwapInt是原子操作,所以必定有一个
线程会先执行完,并且改掉内存偏移地址上的值,那么另一个线程就会出现两次获取内存偏移地址上的值却不一致的情况,
出现这种情况就需要重新获取该值并且在此执行compareAndSwapInt,直到成功为止。
CAS与synchronized比较
CAS支持多个线程并发修改。并发程度高
synchronized一次只有一个线程修改,并发程度较低
CAS只支持一个共享变量的原子操作
synchronized可以对个变量进行加锁
CAS会出现ABA问题
深入理解Atomic原子类的更多相关文章
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ...
- JUC 中的 Atomic 原子类总结
1 Atomic 原子类介绍 Atomic 翻译成中文是原子的意思.在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的.在我们这里 Atomic 是指一个操作是不可中断的.即使是 ...
- Juc中Atomic原子类总结
1 Atomic原子类介绍 2 基本类型原子类 3 数组类型原子类 4 引用类型原子类 5 对象的属性修改类型原子类
- (转)Java atomic原子类的使用方法和原理(一)
在讲atomic原子类之前先看一个小例子: public class UseAtomic { public static void main(String[] args) { AtomicIntege ...
- Atomic原子类
Atomic原子类 Atomic原子类位于并发包java.util.concurrent下的java.util.concurrent.Atomic中. 1. 原子更新基本类型类 使用原子方式更新基本数 ...
- Java线程--Atomic原子类使用
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871241.html Java线程--Atomic原子类使用 package concurr ...
- [Java多线程]-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- J.U.C 系列之Atomic原子类
一 什么是原子类? 所谓原子类必然是具有原子性的类,原子性操作--原子操作,百度百科中给的定义如下 "原子操作(atomic operation)是不需要synchronized" ...
随机推荐
- for_each_node(node)
遍历各个pg_data_t节点. 1.定义在include/linux/nodemask.h中 /* * Bitmasks that are kept for all the nodes. */ en ...
- hdu-2553 N皇后问题(搜索题)
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上. 你的任务是,对于给定的N,求出有多少种合法的放置方法. Inpu ...
- poj--1064
题意:有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的绳子的话,这K条绳子最长能有多长?答案保留到小数点后2位. 思路:这些最大最小化问题大多数可以用二分查找的方法来解题 用 d 表 ...
- HTTP和HTTPS以及两者的区别
HTTP:是互联网上的应用广泛的一种网络协议,是一个客户端和服务器端请求和应答的传输协议,它可以使浏览器更加高效,使网络传输减少. HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版, ...
- POJ 3241 曼哈顿距离最小生成树 Object Clustering
先上几个资料: 百度文库有详细的分析和证明 cxlove的博客 TopCoder Algorithm Tutorials #include <cstdio> #include <cs ...
- python面试题解析(前端、框架和其他)
答: HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
- Linux inode 之我见
Linux硬盘组织方式为:引导区.超级块(superblock),索引结点(inode),数据块(datablock),目录块(diredtory block).其中超级块中包含了关于该硬盘或分区上的 ...
- 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] C】Greedy Arkady
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举那个人收到了几次糖i. 最好的情况显然是其他人都只收到i-1次糖. 然后这个人刚好多收了一次糖 也即 (i-1)kx + x & ...
- 用asp.net+Jquery+Ajax+sqlserver编写的 (英语六级记单词)
开始(英语对程序员的重要性引用) 出处 英语的重要性已经毋庸置疑,对于程序员来说更甚,一些最新的技术资料是英文的,如果想进入外企英语也是一个很重要的条件.对于程序员来说怎样学习好英语,在此谈一下我的一 ...
- Leetcode 419.甲板上的战舰
甲板上的战舰 给定一个二维的甲板, 请计算其中有多少艘战舰. 战舰用 'X'表示,空位用 '.'表示. 你需要遵守以下规则: 给你一个有效的甲板,仅由战舰或者空位组成. 战舰只能水平或者垂直放置.换句 ...