JAVA 原子操作类
上文中,guava代码中就用到了,在这里再专门捋一下
部分内容源自:
https://www.jianshu.com/p/712681f5aecd
https://www.yiibai.com/java_concurrency/concurrency_atomiclong.html
- AtomicReferenceArray<ReferenceEntry<K, V>>
①原子更新基本类型:
AtomicBoolean、AtomicInteger、AtomicLong
②原子更新数组:
AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
③原子更新引用:
AtomicReference、AtomicReferenceFiledUpdater、AtomicMarkableReference
④原子更新字段(属性):
AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference
它们都是使用Unsafe实现的包装类。
- 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 原子操作类的更多相关文章
- Java 并发系列之九:java 原子操作类Atomic(13个)
1. 原子更新基本类型类 2. 原子更新数组 3. 原子更新引用 4. 原子更新属性 5. txt java 原子操作类Atomic 概述 java.util.concurrent.atomic里的原 ...
- Java原子操作类AtomicInteger应用场景
Java中有那么一些类,是以Atomic开头的.这一系列的类我们称之为原子操作类.以最简单的类AtomicInteger为例.它相当于一个int变量,我们执行Int的 i++ 的时候并不是一个原子操作 ...
- Java原子操作类汇总
当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同.比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,而是2.这是 ...
- Java原子操作类,你知道多少?
原子操作类简介 由于synchronized是采用的是悲观锁策略,并不是特别高效的一种解决方案. 实际上,在J.U.C下的atomic包提供了一系列的操作简单,性能高效,并能保证线程安全的类去 更新基 ...
- Java原子操作类汇总(2)
当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同.比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,而是2.这是 ...
- 【Java多线程】Java 原子操作类API(以AtomicInteger为例)
1.java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray, AtomicRef ...
- java中的原子操作类AtomicInteger及其实现原理
/** * 一,AtomicInteger 是如何实现原子操作的呢? * * 我们先来看一下getAndIncrement的源代码: * public final int getAndIncremen ...
- java并发编程基础 --- 7章节 java中的13个原子操作类
当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量 i=1,A线程更新 i+1,B线程也更新 I+1,经过两个线程的操作之后可能 I不等于3,而是等于2.因为A和B线程更 ...
- 并发之java.util.concurrent.atomic原子操作类包
15.JDK1.8的Java.util.concurrent.atomic包小结 14.Java中Atomic包的原理和分析 13.java.util.concurrent.atomic原子操作类包 ...
随机推荐
- OpenStack镜像服务基本操作
查询Glance服务状态 #glance-control all status [root@controller ~]# glance-control all status glance-api (p ...
- 配置允许匿名用户登录访问vsftpd服务,进行文档的上传下载、文档的新建删除等操作
centos7环境下 临时关闭防火墙 #systemctl stop firewalld 临时关闭selinux #setenforce 0 安装ftp服务 #yum install vsftpd - ...
- android 5.0安装应用冲突问题
公司二款产品无法同时安装 为了查看原因 用adb命令安装((adb 命令要配置环境环境,path 盘符+adt-bundle-windows-x86-20140702\sdk\platform-too ...
- [UE4]Format Text
蓝图会自动把字符串中的占位换成参数输入. 字符串不会自动转换,需要手动转换
- unity3d 通过代码建立曲面
using UnityEngine;using System;using System.Collections.Generic; using System.Collections;using Syst ...
- Spring Boot安装及入门实现
在Eclipse里使用Spring boot,首先需要安装Spring boot的插件STS. 注意:STS插件3.7.0以上版本启动需要JDK1.8 打开Eclipse 菜单栏 Help -> ...
- 备用DNS域名服务器
DNS:1.34.151.129,域名:www#eliuliang#com, 个人用解析地址,请勿使用.
- kafka的API操作
在集群的接收端 启动producer 在consumer这边能接收到producer发来的数据
- 【LeetCode】4. 寻找两个有序数组的中位数
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 ...
- 爬虫概念 requests模块
requests模块 - 基于如下5点展开requests模块的学习 什么是requests模块 requests模块是python中原生的基于网络请求的模块,其主要作用是用来模拟浏览器发起请求.功能 ...