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

部分内容源自:

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

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

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

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

  1. public class MainTest {
  2. private static String[] source = new String[10];
  3. private static AtomicReferenceArray<String> atomicReferenceArray = new AtomicReferenceArray<String>(source);
  4.  
  5. public static void main(String[] args) throws InterruptedException {
  6. for (int i = 0; i < atomicReferenceArray.length(); i++) {
  7. atomicReferenceArray.set(i, "item-2");
  8. }
  9.  
  10. Thread t1 = new Thread(new Increment());
  11. Thread t2 = new Thread(new Compare());
  12. t1.start();
  13. t2.start();
  14.  
  15. t1.join();
  16. t2.join();
  17. }
  18.  
  19. static class Increment implements Runnable {
  20. public void run() {
  21. for (int i = 0; i < atomicReferenceArray.length(); i++) {
  22. String add = atomicReferenceArray.getAndSet(i, "item-" + (i + 1));
  23. System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: " + add);
  24. }
  25. }
  26. }
  27.  
  28. static class Compare implements Runnable {
  29. public void run() {
  30. for (int i = 0; i < atomicReferenceArray.length(); i++) {
  31. System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: "
  32. + atomicReferenceArray.get(i));
  33. boolean swapped = atomicReferenceArray.compareAndSet(i, "item-2", "updated-item-2");
  34. System.out.println("Item swapped: " + swapped);
  35. if (swapped) {
  36. System.out
  37. .println("Thread " + Thread.currentThread().getId() + ", index " + i + ", updated-item-2");
  38. }
  39. }
  40. }
  41. }
  42. }

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

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

  1. class Node {
  2. private volatile Node left, right;
  3.  
  4. private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
  5. AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
  6. private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
  7. AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
  8.  
  9. Node getLeft() { return left; }
  10. boolean compareAndSetLeft(Node expect, Node update) {
  11. return leftUpdater.compareAndSet(this, expect, update);
  12. }
  13. // ... and so on
  14. }}
  1. public
  2. class BufferedInputStream extends FilterInputStream {
  3.  
  4. protected volatile byte buf[];
  5.  
  6. /*
  7. * 原子的更新内部数组,比如扩容、关闭时,
  8. */
  9. private static final
  10. AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
  11. AtomicReferenceFieldUpdater.newUpdater
  12. (BufferedInputStream.class, byte[].class, "buf");
  13.  
  14. public void close() throws IOException {
  15. byte[] buffer;
  16. while ( (buffer = buf) != null) {
  17. //放在一个循环中,如果CAS更新失败,那么就读取最新的buf引用,继续CAS更新
  18. if (bufUpdater.compareAndSet(this, buffer, null)) {
  19. InputStream input = in;
  20. in = null;
  21. if (input != null)
  22. input.close();
  23. return;
  24. }
  25. }
  26. }
  27. }

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. OpenStack镜像服务基本操作

    查询Glance服务状态 #glance-control all status [root@controller ~]# glance-control all status glance-api (p ...

  2. 配置允许匿名用户登录访问vsftpd服务,进行文档的上传下载、文档的新建删除等操作

    centos7环境下 临时关闭防火墙 #systemctl stop firewalld 临时关闭selinux #setenforce 0 安装ftp服务 #yum install vsftpd - ...

  3. android 5.0安装应用冲突问题

    公司二款产品无法同时安装 为了查看原因 用adb命令安装((adb 命令要配置环境环境,path 盘符+adt-bundle-windows-x86-20140702\sdk\platform-too ...

  4. [UE4]Format Text

    蓝图会自动把字符串中的占位换成参数输入. 字符串不会自动转换,需要手动转换

  5. unity3d 通过代码建立曲面

    using UnityEngine;using System;using System.Collections.Generic; using System.Collections;using Syst ...

  6. Spring Boot安装及入门实现

    在Eclipse里使用Spring boot,首先需要安装Spring boot的插件STS. 注意:STS插件3.7.0以上版本启动需要JDK1.8 打开Eclipse 菜单栏 Help -> ...

  7. 备用DNS域名服务器

    DNS:1.34.151.129,域名:www#eliuliang#com, 个人用解析地址,请勿使用.

  8. kafka的API操作

    在集群的接收端 启动producer 在consumer这边能接收到producer发来的数据

  9. 【LeetCode】4. 寻找两个有序数组的中位数

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2  ...

  10. 爬虫概念 requests模块

    requests模块 - 基于如下5点展开requests模块的学习 什么是requests模块 requests模块是python中原生的基于网络请求的模块,其主要作用是用来模拟浏览器发起请求.功能 ...