java源码-AtomicReference
开篇
The AtomicReference class provides reference objects that may be read and written atomically, so when multiple threads try to reach them at the same time, only one will be able to do so.
换句话说就是AtomicReference提供Object对象的原子类操作,提供了更加灵活的操作。
AtomicReference类和构造器
AtomicReference的构造函数类构造器有两个:
- 无参构造函数采用默认值初始化为0
- 有参数构造函数直接用initialValue来value的
AtomicReference类变量需要注意的两个点:
- AtomicReference的关键逻辑在于static代码快中通过unsafe接口初始化value的内存地址,后续直接通过内存地址进行操作。
- AtomicReference的value是用volatile进行修饰保证变量的可见性
public class AtomicReference<V> implements java.io.Serializable { private static final long serialVersionUID = -1848883965231344442L; private static final Unsafe unsafe = Unsafe.getUnsafe(); // 保存AtomicLong中value的内存地址便于快速操作 private static final long valueOffset; // 获取value的内存地址的逻辑操作 static { try { valueOffset = unsafe.objectFieldOffset (AtomicReference.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile V value; // 以传入的initialValue初始化value对象 public AtomicReference(V initialValue) { value = initialValue; } // 以传入的null初始化value对象 public AtomicReference() { } }
AtomicReference的get操作
AtomicReference的get操作相比之前的AtomicLong的get操作少了getAndIncrement()等自增自减的操作,只支持整个对象的更新。
- getAndSet()方法取出原来的值并更新新值newValue
- getAndUpdate()、getAndAccumulate()等操作通过compareAndSet()操作完成原子性的对象更新
public final V get() { return value; } @SuppressWarnings("unchecked") public final V getAndSet(V newValue) { return (V)unsafe.getAndSetObject(this, valueOffset, newValue); } public final V getAndUpdate(UnaryOperator<V> updateFunction) { V prev, next; do { prev = get(); next = updateFunction.apply(prev); } while (!compareAndSet(prev, next)); return prev; } public final V getAndAccumulate(V x, BinaryOperator<V> accumulatorFunction) { V prev, next; do { prev = get(); next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(prev, next)); return prev; }
AtomicReference的set操作
AtomicReference的set操作是通过unsafe.compareAndSwapObject()方法实现原子性操作,updateAndGet()方法只有在原子性更新成功后才能返回更新后的对象。
public final void set(V newValue) { value = newValue; } public final void lazySet(V newValue) { unsafe.putOrderedObject(this, valueOffset, newValue); } public final boolean compareAndSet(V expect, V update) { return unsafe.compareAndSwapObject(this, valueOffset, expect, update); } public final boolean weakCompareAndSet(V expect, V update) { return unsafe.compareAndSwapObject(this, valueOffset, expect, update); } public final V updateAndGet(UnaryOperator<V> updateFunction) { V prev, next; do { prev = get(); next = updateFunction.apply(prev); } while (!compareAndSet(prev, next)); return next; } public final V accumulateAndGet(V x, BinaryOperator<V> accumulatorFunction) { V prev, next; do { prev = get(); next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(prev, next)); return next; }
案例
// AtomicReferenceTest.java的源码 import java.util.concurrent.atomic.AtomicReference; public class AtomicReferenceTest { public static void main(String[] args){ // 创建两个Person对象,它们的id分别是101和102。 Person p1 = new Person(101); Person p2 = new Person(102); // 新建AtomicReference对象,初始化它的值为p1对象 AtomicReference ar = new AtomicReference(p1); // 通过CAS设置ar。如果ar的值为p1的话,则将其设置为p2。 ar.compareAndSet(p1, p2); Person p3 = (Person)ar.get(); System.out.println("p3 is "+p3); System.out.println("p3.equals(p1)="+p3.equals(p1)); } } class Person { volatile long id; public Person(long id) { this.id = id; } public String toString() { return "id:"+id; } } 运行结果 p3 is id:102 p3.equals(p1)=false
文末彩蛋
对高手而言 自律是一种生活方式 若只是间歇性的热血沸腾 不可能成功 很多工作拼的不是才华 而是持续和稳定 所以先把你的勤奋变成现在进行时吧! 剔除自我感动,也学会自我成全 工作、代码、写作、跑步,近乎苦行僧般的生活让我感到很踏实
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Go+Web前端全栈班
不忘初心,砥砺前行 朋友们、同学们, 大家好.。江哥创业了, 希望得到大家一如既往的支持, 谢谢! 指趣学院是江哥和一群志同道合的朋友共同创建的“在线IT创新教育平台“,核心成员大部分来自国内外一线企业及学术研究机构。希望通过一线开发工程师和优秀讲师共同研发课程的方式, 给学习者带来持续且美好的改变,为学员提供一个终身在线学习平台,以敏捷的速度和锐利的视角将一线企业前沿应用技术转化为课程;通过在线教育的形式,让更多热爱IT学习的人,可以学到更多、更专业的IT技能;也希望能充分发挥网络的优势,促进解决当下教育资源分布不均的问题。 除此之外, 指趣学院还希望身体力行, 积极投身教育公益事业, 每个班级、每套视频均会给予1-2个免费名额奖励那些家庭困难,但仍坚持学习、努力实现梦想的学员。 指趣学院地址: www.it666.com www.itzb.com(备案中, 后期将通过双域名同时指向) 学科介绍 指趣学院现已开设两个学科, Web前端和Golang后端, 后续将陆续开设Python、Java、UI设计等其它热门学科 开设Web前端学科原因: 4G引爆了智能手机、引爆了移动互联网, 让...
- 下一篇
Python网络编程(子进程的创建与处理、简单群聊工具)
前言: 昨天我们已经了解了多进程的原理以及它的实际使用 Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次, 但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。 子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以, 父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。 Python的os模块封装了常见的系统调用,其中就包括fork,可以在Python程序中轻松创建子进程 既然是进程那么就会有运行和退出 接下来我们就来了解一下进程的退出以及处理 孤儿进程: 当 父进程优 先于子进程 退出,此时 子进程就会 成为孤儿进程 特征: 孤儿进程会被系统指定进程收养,即 系统进程会 成为 这个孤儿进程 新的父进程,系统进程 会自动处理进程 退出状态 僵尸进程: 当 子进程优 先于父进程 退出, 父进程没有 处理子进程的 退出状态 此时子进程 就...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果