上文中,guava代码中就用到了,在这里再专门捋一下

部分内容源自:

https://www.jianshu.com/p/712681f5aecd

https://www.yiibai.com/java_concurrency/concurrency_atomiclong.html

AtomicReferenceArray<ReferenceEntry<K, V>>
根据变量类型的不同,Atomic包中的这12个原子操作类可以分为4种类型:
①原子更新基本类型AtomicBoolean、AtomicInteger、AtomicLong
②原子更新数组AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
③原子更新引用AtomicReference、AtomicReferenceFiledUpdater、AtomicMarkableReference
④原子更新字段(属性)AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference
它们都是使用Unsafe实现的包装类。
 
对于原子更新类基本操作,可以看到AtomicInteger中基本有以下一些方法,其他也都差不多,用法简单
        Executor executor = Executors.newFixedThreadPool(3);
AtomicInteger atomicInteger = new AtomicInteger(0);
for(int i = 0; i < 10; i++){
executor.execute(()->{
System.out.println("atomicInteger的当前值:" + atomicInteger.addAndGet(1));
});
}

原子更新数组,例AtomicReferenceArray,用法抄自上文,实际就是基于cas的操作

public class MainTest {
private static String[] source = new String[10];
private static AtomicReferenceArray<String> atomicReferenceArray = new AtomicReferenceArray<String>(source); public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < atomicReferenceArray.length(); i++) {
atomicReferenceArray.set(i, "item-2");
} Thread t1 = new Thread(new Increment());
Thread t2 = new Thread(new Compare());
t1.start();
t2.start(); t1.join();
t2.join();
} static class Increment implements Runnable {
public void run() {
for (int i = 0; i < atomicReferenceArray.length(); i++) {
String add = atomicReferenceArray.getAndSet(i, "item-" + (i + 1));
System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: " + add);
}
}
} static class Compare implements Runnable {
public void run() {
for (int i = 0; i < atomicReferenceArray.length(); i++) {
System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: "
+ atomicReferenceArray.get(i));
boolean swapped = atomicReferenceArray.compareAndSet(i, "item-2", "updated-item-2");
System.out.println("Item swapped: " + swapped);
if (swapped) {
System.out
.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", updated-item-2");
}
}
}
}
}

AtomicReferenceFiledUpdater https://github.com/aCoder2013/blog/issues/10 这个blog写的真不错,在jdk中有很多应用。比如对buf的更新等

一个基于反射的工具类,它能对指定类的指定的volatile引用字段进行原子更新。(注意这个字段不能是private的)

 class Node {
private volatile Node left, right; private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right"); Node getLeft() { return left; }
boolean compareAndSetLeft(Node expect, Node update) {
return leftUpdater.compareAndSet(this, expect, update);
}
// ... and so on
}}
public
class BufferedInputStream extends FilterInputStream { protected volatile byte buf[]; /*
* 原子的更新内部数组,比如扩容、关闭时,
*/
private static final
AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
AtomicReferenceFieldUpdater.newUpdater
(BufferedInputStream.class, byte[].class, "buf"); public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
//放在一个循环中,如果CAS更新失败,那么就读取最新的buf引用,继续CAS更新
if (bufUpdater.compareAndSet(this, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)
input.close();
return;
}
}
}
}

AtomicStampedReference 通过包装[E,Integer]的元组来对对象标记版本戳stamp,从而避免ABA问题

JAVA 原子操作类的更多相关文章

  1. Java 并发系列之九:java 原子操作类Atomic(13个)

    1. 原子更新基本类型类 2. 原子更新数组 3. 原子更新引用 4. 原子更新属性 5. txt java 原子操作类Atomic 概述 java.util.concurrent.atomic里的原 ...

  2. Java原子操作类AtomicInteger应用场景

    Java中有那么一些类,是以Atomic开头的.这一系列的类我们称之为原子操作类.以最简单的类AtomicInteger为例.它相当于一个int变量,我们执行Int的 i++ 的时候并不是一个原子操作 ...

  3. Java原子操作类汇总

    当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同.比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,而是2.这是 ...

  4. Java原子操作类,你知道多少?

    原子操作类简介 由于synchronized是采用的是悲观锁策略,并不是特别高效的一种解决方案. 实际上,在J.U.C下的atomic包提供了一系列的操作简单,性能高效,并能保证线程安全的类去 更新基 ...

  5. Java原子操作类汇总(2)

    当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同.比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,而是2.这是 ...

  6. 【Java多线程】Java 原子操作类API(以AtomicInteger为例)

    1.java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray, AtomicRef ...

  7. java中的原子操作类AtomicInteger及其实现原理

    /** * 一,AtomicInteger 是如何实现原子操作的呢? * * 我们先来看一下getAndIncrement的源代码: * public final int getAndIncremen ...

  8. java并发编程基础 --- 7章节 java中的13个原子操作类

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量 i=1,A线程更新 i+1,B线程也更新 I+1,经过两个线程的操作之后可能 I不等于3,而是等于2.因为A和B线程更 ...

  9. 并发之java.util.concurrent.atomic原子操作类包

    15.JDK1.8的Java.util.concurrent.atomic包小结 14.Java中Atomic包的原理和分析 13.java.util.concurrent.atomic原子操作类包 ...

随机推荐

  1. jquery 点击元素以外任意地方隐藏该元素的方法

    文章来源:百度知道 我的思路是给body绑定一个click事件,然后判断当前鼠标点击的区域是当前元素还是元素以外区域,如果点击对象不是当前元素,则隐藏该元素. 假设对象的id为divBtn,则代码如下 ...

  2. 数据库的ds命令

    Mysqi      数据库: 理一下数据库的格式: mysqi 关系型数据库,(表的概念) node.js 非关系性数据库  (json) 结构:数据库存放多张表,每个表可以存放多个字段,每个字段可 ...

  3. 禅道在docker上部署与迁移

    一.禅道部署 1.下载地址 禅道开源版:   http://dl.cnezsoft.com/zentao/docker/docker_zentao.zip 数据库用户名: root,默认密码: 123 ...

  4. [UE4]旋转小地图

    一.Canvas Panel的旋转原点是Render Transform——>Pivot,Pivot坐标的取值范围是0到1,左上角的pivot坐标是[0,0],右下角的pivot坐标是[1,1] ...

  5. 挂载本地iso镜像

    挂载本地iso镜像 [root@linux-node1 ~]# mkdir -p /disk/iso [root@linux-node1 ~]# cd /disk/iso/ [root@linux-n ...

  6. nonlocal和global

    获取变量时遵循LEGB原则,修改变量时需要global/nonlocal进行修改 global # global的使用 函数外定义了全局变量: global关键字在函数内会修改全局变量 函数外没定义全 ...

  7. virtualbox创建虚拟机

    两种方式: 1.使用.vdi硬盘镜像文件 2.使用操作系统新建 方法1: #结束! 方法2:

  8. 【LeetCode】2. Add Two Numbers 两数相加

    给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和 ...

  9. solr 打分和排序机制(转载)

    以下来自solr in action. 包含: 词项频次.查询词项出现在当前查询文档中的次数. 反向文档频次.查询词项出现在所有文档总的次数. 此项权重. 标准化因子: 字段规范: 文档权重. 字段权 ...

  10. ECharts动态加载堆叠柱状图的实例

    一.引入echarts.js文件(下载页:http://echarts.baidu.com/download.html) 二.HTML代码: <div style="width: 10 ...