Atomic 原子操作类包

Atomic包 主要是在多线程环境下,无锁的进行原子操作。核心操作是基于UnSafe类实现的CAS方法

CAS

CAS: compareAndSwap :传入两个值:期望值和新值,判断原有值与期望值相等,则给其赋新值,否则不做任何操作。

CAS硬件支持

现代的CPU提供了特殊的指令,可以自动更新共享数据,而且能够检测到其他线程的干扰。

Atomic源码

以AtomicInteger为例(AtomicBoolean也是把boolen转为int)

public class AtomicInteger extends Number implements java.io.Serializable {

//序列化相关

private static final long serialVersionUID = 6214790243416807050L;

//Unsafe类

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); }

}

//value值,因为无锁使用volatile保证线程加载到最新的值

private volatile int value;

//初始化

public AtomicInteger(int initialValue) {

value = initialValue;

}

public AtomicInteger() {

}

//获取当前值

public final int get() {

return value;

}

//赋值

public final void set(int newValue) {

value = newValue;

}

//延迟赋值,不保证新的赋值能立即被其他线程获取到

public final void lazySet(int newValue) {

unsafe.putOrderedInt(this, valueOffset, newValue);

}

//返回旧值并赋新值

public final int getAndSet(int newValue) {

for (;;) {// 等同于while(true)

int current = get();//获取旧值

if (compareAndSet(current, newValue))//以CAS方式赋值,直到成功返回

return current;

}

}

//对比期望值与value,不同返回false。相同将update赋给value 返回true

public final boolean compareAndSet(int expect, int update) {

return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

}

//与compareAndSet实现相同(可能为了以后更改)

public final boolean weakCompareAndSet(int expect, int update) {

return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

}

//自增 i++

public final int getAndIncrement() {

for (;;) {

int current = get();

int next = current + 1;

if (compareAndSet(current, next))

return current;

}

}

//自减 i--

public final int getAndDecrement() {

for (;;) {

int current = get();

int next = current - 1;

if (compareAndSet(current, next))

return current;

}

}

//自定义增量数

public final int getAndAdd(int delta) {

for (;;) {

int current = get();

int next = current + delta;

if (compareAndSet(current, next))

return current;

}

}

//++i 返回自增后的值

public final int incrementAndGet() {

for (;;) {

int current = get();

int next = current + 1;

if (compareAndSet(current, next))

return next;

}

}

//--i 返回减少后的值

public final int decrementAndGet() {

for (;;) {

int current = get();

int next = current - 1;

if (compareAndSet(current, next))

return next;

}

}

//返回加上delta后的值

public final int addAndGet(int delta) {

for (;;) {

int current = get();

int next = current + delta;

if (compareAndSet(current, next))

return next;

}

}

/**

* Returns the String representation of the current value.

* @return the String representation of the current value.

*/

public String toString() {

return Integer.toString(get());

}

public int intValue() {

return get();

}

public long longValue() {

return (long)get();

}

public float floatValue() {

return (float)get();

}

public double doubleValue() {

return (double)get();

}

}

CAS的ABA问题

ABA问题:有两个线程,x线程读取值为A ,y线程读取值为A 并赋值为B,B线程再修改会A,此时x线程以A为旧值并赋新值仍然是成功的,

因为线程x不知道变量值经过A->B->A的修改。

AtomicStampedReference 解决ABA问题

先看看如何使用:

AtomicStampedReference asr= new AtomicStampedReference(1,0);

int stamp= asr.getStamp();

System.out.println(asr.compareAndSet(1,2,stamp,stamp+1));//true

System.out.println(asr.compareAndSet(2,1,stamp,stamp+1));//false

System.out.println(asr.compareAndSet(1,1,stamp+1,stamp+2));//false

System.out.println(asr.getReference());//2

对比AtomicInteger,可见AtomicStampedReference的构造函数多了一个参数、compareAndSet方法多了两个参数,看一下源码:

//对比AtomicInteger构造函数多了stamp参数

public AtomicStampedReference(V initialRef, int initialStamp) {

pair = Pair.of(initialRef, initialStamp);

}

private static class Pair {

final T reference;

final int stamp;

private Pair(T reference, int stamp) {

this.reference = reference;

this.stamp = stamp;

}

static Pair of(T reference, int stamp) {

return new Pair(reference, stamp);

}

}

//对比AtomicInteger value由int 改为Pair

private volatile Pair pair;

public boolean compareAndSet(V expectedReference,

V newReference,

int expectedStamp,

int newStamp) {

Pair current = pair;

return

expectedReference == current.reference && //判断期望值与旧值是否相同

expectedStamp == current.stamp && //判断期望版本戳与旧版本戳是否相同

((newReference == current.reference &&

newStamp == current.stamp) || //如果值和戳没变化不执行下一行cas赋值代码

casPair(current, Pair.of(newReference, newStamp)));//cas赋值代码

}

//还是调用unsafe类

private boolean casPair(Pair cmp, Pair val) {

return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);

}

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. 原子更新基本类型类 使用原子方式更新基本数 ...

多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

[Java多线程]-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

J.U.C 系列之Atomic原子类

一 什么是原子类? 所谓原子类必然是具有原子性的类,原子性操作--原子操作,百度百科中给的定义如下 "原子操作(atomic operation)是不需要synchronized" ...

Spring.NET学习笔记——目录(原)

目录 前言 Spring.NET学习笔记——前言 第一阶段:控制反转与依赖注入IoC&DI Spring.NET学习笔记1——控制反转(基础篇) Level 200 Spring.NET学习笔 ...

随机推荐

[汇编与C语言关系]4. 结构体和联合体

用反汇编的方法研究一下C语言的结构体: #include int main(int argc, char ** argv) { struct { char a; sho ...

AndroidStudio学习笔记-第一个安卓程序

要带一个本科生做一部分跟安卓有点关系的项目,于是趁着机会学习一下编写安卓程序. 第一篇材料来自谷歌官方,传送门:https://developer.android.com/training/basic ...

windows 10

http://auPL.v4.b1.download.windowsupdate.com/c/updt/2015/07/10240.16384.150709-1700.th1_clientchina_ ...

Android蓝牙连接以及数据接收发送

1.加入权限

CSS 高级技巧汇总

在我们平时写代码的时候没有没有掌握一些CSS技巧呢? 今天给大家分享一个.大家务必掌握这些小技巧,会让你非常高效率的写出网页的. ◆使用 :not ...

微信小程序简单入门1

参考文档:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html 1  创建项目 开发者工具安装完成后,打开并使用微信扫码登录.选择创建"项 ...

遇到的问题&思考

MYSQL需要批量修改表前缀: http://jingyan.baidu.com/article/11c17a2c742561f446e39d2f.html Select CONCAT( 'ALTER ...

PhysicalDrive

由于"\"是C/C+中转义符, "\\\\.\\"就相当于\\.\ 在Windows中 \\.\ 前缀用于标识设备,其中的"."表示本地计算 ...

Delphi字符串、PChar与字符数组之间的转换

来自:http://my.oschina.net/kavensu/blog/193719 ------------------------------------------------------- ...

java 中的valueOf方法和强转

case1:Object 对象转String 需要强调的是String.valueOf()方法,当参数为类型是object,且值时null的时候他的处理方式 public static String ...

atomic原子类实现机制_JUC学习笔记--Atomic原子类相关推荐

  1. Spring.NET学习笔记——目录(原)

    目录 前言 Spring.NET学习笔记--前言 第一阶段:控制反转与依赖注入IoC&DI Spring.NET学习笔记1--控制反转(基础篇) Level 200 Spring.NET学习笔 ...

  2. C# 子类实例化基类 基类使用不了子类的方法_C#学习笔记09--构造方法/析构方法/继承/多态/封装...

    一.构造方法 当创建一个类时, 系统会自动创建一个默认的无参构造方法, 这个方法和类同名, 在创建对象的时候自动调用. 默认的构造方法里面什么也没有, 重写之后就可以在创建对象的时候同时搞点事情了. ...

  3. atomic原子类实现机制_Java并发包-atomic包-让您彻底掌握AtomicInteger源码

    从这一篇文章开始,我开始对并发包的atomic包进行源码解析,首先通过下面的图了解以下atomic包中的类都是有哪些? atomic包中的所有类 这一篇文章首先对AtomicInteger进行讲解.在 ...

  4. TVM中的auto-scheduling机制(Ansor)学习笔记

    背景 TVM继承了Halide中算法(Algorithm)与调度(Schedule)分离的思想.用户使用TE(Tensor expression)这种DSL定义计算(算法),然后编译器优化相应的sch ...

  5. NumPy————NumPy广播机制的学习笔记

    1 致谢 感谢网友"FINTHON"的帮助, 原文链接如下: https://finthon.com/numpy-broadcast/ 2 前言 今天在学习K-means算法~ 想 ...

  6. Java并发23:Atomic系列-普通原子类型AtomicXxxx学习笔记

    [超级链接:Java并发学习系列-绪论] [系列概述: Java并发22:Atomic系列-原子类型整体概述与类别划分] 本章主要对普通原子类型进行学习. 1.普通原子类型 在java.util.co ...

  7. C# 子类实例化基类 基类使用不了子类的方法_C#学习笔记11--接口/泛型

    一.接口 1.1简介: 接口是一种特殊的引用类型, 和类很相似. 它定义了属性, 方法, 事件, 这些都作为接口的成员/ 接口中只包含成员的声明, 成员的定义是派生类的责任(谁继承谁实现). 接口在某 ...

  8. python函数参数传递机制_Python 学习笔记(一) 理解Python的函数传参机制

    对于刚接触Python不久的新手,Python的函数传参机制往往会让人迷惑.学过C的同学都知道函数参数可以传值或者传地址.比如下面这段代码 点击(此处)折叠或打开 void func(int inpu ...

  9. 计算机视觉中的注意力机制的学习笔记

    1 介绍 关于注意力机制(Attension)的综述请参考博文<综述|计算机视觉中的注意力机制> 关于Attention机制,我总觉得是一个很有趣的话题,因为根据"万能拟合器&q ...

最新文章

  1. MySQL 讨厌哪种类型的查询
  2. php tp5 redis的使用(亲测)
  3. 接入淘宝API(PHP版本)
  4. java 运行 .jar 文件乱码
  5. OpenCV学习笔记(十八):凸包,最小包围区域算子:convexHull(),minAreaRect(),minEnclosingTriangle(),minEnclosingCircle()
  6. linux下nmap工具的使用
  7. [转] 面向对象编程 - 类和实例
  8. node.js 数据库操作工具类封装
  9. Android图片加载那些事(一)-实现加载手机中的所有图片
  10. 使用arcgis、matlab与R语言GD包进行地理探测器 批量运行,并导出探测结果
  11. Vue开发环境搭建详解
  12. 【DC-DC开关电源芯片的使用(LM2596)】
  13. 无监督学习——非负矩阵分解(NMF)
  14. 铜陵学院计算机程序设计大赛,ACM程序设计大赛
  15. android 多语言国家化对照表(超详细)
  16. 10个每个人都用得到的视频下载网站
  17. 国内工业机器人发展水平综述
  18. css —— 文字添加白色描边
  19. MFC修改界面图标时,已导入.ico文件,但是程序运行后,界面不显示更新后的新图标
  20. 一入IT深似海 从此妹子为路人

热门文章

  1. ATS 5.3.0日志字段分析(续)
  2. Maya 2020面部绑定动画学习视频教程 Facial Rigging 101 – Maya 2020
  3. ceph-deploy rpm包的制作
  4. 谁知道静态成员的纠结心境
  5. javascript数组集锦
  6. Vue组件绑定自定义事件
  7. 转: IO设计模式:Reactor和Proactor对比
  8. 计量注册师考试一些关于期限、时间、机构的总结
  9. C++ primer第五版随笔--2015年1月6日
  10. Android提示框与通知的使用