Atomic原子类
Atomic原子类
Atomic原子类位于并发包java.util.concurrent
下的java.util.concurrent.Atomic
中。
1. 原子更新基本类型类
使用原子方式更新基本数据类型,Atomic提供以下3个类
- AtomicInteger:原子更新整型
- AtomicBoolean:原子更新布尔型
- AtomicLong:原子更新长整型
以AtomicInteger为例进行介绍:
// 获取index = i位置元素的值
public final int get(int i)
// 返回index = i位置的当前的值,并将其设置为新值newValue
public final int getAndSet(int i, int newValue)
// 获取index = i位置元素的值,并让该位置的元素自增
public final int getAndIncrement(int i)
// 获取index = i位置元素的值,并让该位置的元素自减
public final int getAndDecrement(int i)
// 获取index = i位置元素的值,并加上预期的值
public final int getAndAdd(int delta)
// CAS操作,返回是否操作成功
boolean compareAndSet(int expect, int update)
//最终将index = i位置元素设置为newValue,使用lazySet可能导致其他线程在之后一小段时间仍可读取旧值。
public final void lazySet(int i, int newValue)
Demo:
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerDemo {
public static void main(String[] args) {
int tempValue = 0;
AtomicInteger i = new AtomicInteger(0);
tempValue = i.getAndSet(3);
System.out.println("先获取当前值后设置新值");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 0 3
tempValue = i.getAndIncrement();
System.out.println("先获取当前值后使当前值自增");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 3 4
tempValue = i.incrementAndGet();
System.out.println("先使当前值自增后获取值");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 5 5
tempValue = i.getAndAdd(5);
System.out.println("先获取当前值再使当前值加上一个值");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 5 10
}
}
AtomicInteger能够解决volatile关键字在面对count++
操作时不能保证原子性的问题。使用AtomicInteger后,不需要加锁也可以保证线程安全。
多线程环境下采用synchronized关键字加锁保证线程安全
class test01 {
private volatile int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
多线程环境下采用AtomicInteger原子类保证线程安全(无需加锁)
class test02 {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count++;
}
public int getCount() {
return count.get();
}
}
AtomicInteger 类主要利用 CAS (compare and swap) + volatile 和 native 方法来保证原子操作,从而避免 synchronized 的高开销,执行效率大为提升。
2. 原子更新数组类型类
通过原子方式更新数组里的某个元素,Atomic包提供了以下类:
- AtomicIntegerArray:原子更新整型数组
- AtomicLongArray:原子更新长整型数组
- AtomicReferenceArray:原子更新引用类型数组
以AtomicIntegerArray为例进行介绍:
import java.util.concurrent.atomic.AtomicIntegerArray;
public class AtomicIntegerArrayDemo {
public static void main(String[] args) {
int tempValue = 0;
int[] arr = {1, 2, 3, 4, 5};
AtomicIntegerArray i = new AtomicIntegerArray(arr);
for (int j = 0; j < arr.length; j++) {
System.out.print(i.get(j) + " "); // 1 2 3 4 5
}
System.out.println();
tempValue = i.getAndSet(0, 2);
System.out.println("先获取索引处的当前值后设置新值");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 1 [2, 2, 3, 4, 5]
tempValue = i.getAndIncrement(0);
System.out.println("先获取索引处的当前值后使当前值自增");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 2 [3, 2, 3, 4, 5]
tempValue = i.incrementAndGet(0);
System.out.println("先使索引处的当前值自增后获取值");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 4 [4, 2, 3, 4, 5]
tempValue = i.getAndAdd(0, 5);
System.out.println("先获取索引处的当前值再使当前值加上一个值");
System.out.println("tempValue = " + tempValue + "; i = " + i); // 4 [9, 2, 3, 4, 5]
}
}
3. 原子更新引用类型类
如果需要原子更新多个变量,就需要使用这个原子更新引用类型提供的类:
- AtomicReference:原子更新引用类型
- AtomicReferenceFieldUpdater:原子更新引用类型里的字段
- AtomicMarkableReference:原子更新打游标记位的引用类型
Demo:
import java.util.concurrent.atomic.AtomicReference;
public class AtomicReferenceDemo {
public static void main(String[] args) {
AtomicReference<User> atomicUserRef = new AtomicReference<>();
User user = new User("AAA", 10);
atomicUserRef.set(user);
User updateUser = new User("BBB", 20);
// 调用CAS方法
atomicUserRef.compareAndSet(user, updateUser);
// 调用get方法并获取姓名和年龄打印
System.out.println(atomicUserRef.get().getName()); // BBB
System.out.println(atomicUserRef.get().getAge()); // 20
}
/**
* 静态内部类User
*/
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
}
4. 原子更新字段类
需要原子更新某个类中的对象属性时,需要使用原子更新字段类:
- AtomicIntegerFieldUpdater:原子更新整型字段的更新器
- AtomicLongFieldUpdater:原子更新长整型字段的更新器
- AtomicStampedReference:原子更新带有版本号的引用类型(解决ABA问题)
要想原子更新对象的属性需要两步:
- 因为原子更新字段类都是抽象类,所以每次使用时都必须使用静态方法
new Updater()
创建一个更新器,并且需要设置想要更新的类和属性; - 更新的对象属性必须使用
public volatile
修饰。
Demo:
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicIntegerFieldUpdaterDemo {
public static void main(String[] args) {
// 使用newUpdater()方法创建更新器
AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
User user = new User("AAA", 10);
System.out.println(a.getAndIncrement(user)); // 10
System.out.println(a.get(user)); // 11
}
/**
* 静态内部类User
* 要更新的字段采用public volatile修饰
*/
static class User {
private String name;
public volatile int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
}
Atomic原子类的更多相关文章
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ...
- Juc中Atomic原子类总结
1 Atomic原子类介绍 2 基本类型原子类 3 数组类型原子类 4 引用类型原子类 5 对象的属性修改类型原子类
- (转)Java atomic原子类的使用方法和原理(一)
在讲atomic原子类之前先看一个小例子: public class UseAtomic { public static void main(String[] args) { AtomicIntege ...
- JUC 中的 Atomic 原子类总结
1 Atomic 原子类介绍 Atomic 翻译成中文是原子的意思.在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的.在我们这里 Atomic 是指一个操作是不可中断的.即使是 ...
- Java线程--Atomic原子类使用
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871241.html Java线程--Atomic原子类使用 package concurr ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- [Java多线程]-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- J.U.C 系列之Atomic原子类
一 什么是原子类? 所谓原子类必然是具有原子性的类,原子性操作--原子操作,百度百科中给的定义如下 "原子操作(atomic operation)是不需要synchronized" ...
- JUC学习笔记--Atomic原子类
J.U.C 框架学习顺序 http://blog.csdn.net/chen7253886/article/details/52769111 Atomic 原子操作类包 Atomic包 主要是在多线程 ...
随机推荐
- MySQL 高级性能优化架构 千万级高并发交易一致性系统基础
一.MySQL体系架构 由图,可以看出MySQL最上层是连接组件.下面服务器是由连接池.管理服务和工具组件.SQL接口.查询解析器.查询优化器.缓存.存储引擎.文件系统组成. 1.连接池 管理.缓冲用 ...
- RecyclerView设置空视图
RecyclerView貌似不能直接设置空视图,所以可以自定义一个RecyclerView继承自RecyclerView并设置一个数据监听者监视数据状态. MyCyclerView.java pack ...
- Elasticsearch及相关插件的安装
Elasticsearch及相关插件的安装 1.安装Elasticsearch并启动服务 2.安装第三方插件 2.1.Head插件 是Elasticsearch的一个集群管理工具,可以通过它来查看和搜 ...
- 《Python编程第4版 下》高清PDF|百度网盘免费下载|Python基础编程
<Python编程第4版 下>高清PDF|百度网盘免费下载|Python基础编程 提取码:tz5v 当掌握Python的基础知识后,你要如何使用Python?Python编程(第四版)为这 ...
- Django学习路24_乘法和除法
urls 中 url(r'getnum',views.getnum) views.py 中添加对应的函数 def getnum(request): num = 5 context_num = { 'n ...
- PHP mt_getrandmax() 函数
实例 返回通过调用 mt_rand() 函数显示的随机数的最大可能值: <?phpecho(mt_getrandmax()); ?>高佣联盟 www.cgewang.com 定义和用法 m ...
- luogu P5473 [NOI2019]I 君的探险 交互 随机 二分 分治 整体二分
LINK:I 君的探险 神仙题! 考虑一个暴力的做法 每次点亮一个点 询问全部点 这样询问次数为 \(\frac{n\cdot (n-1)}{2}\) 可以通过前5个点. 考虑都为A的部分分 发现一个 ...
- 【原创】xenomai与VxWorks实时性对比(Jitter对比)
版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ (下面数据,仅供个人参考) 可能大部分人一直好奇Vx ...
- asp.net core 3.1 自定义中间件实现jwt token认证
asp.net core 3.1 自定义中间件实现jwt token认证 话不多讲,也不知道咋讲!直接上代码 认证信息承载对象[user] /// <summary> /// 认证用户信息 ...
- CI4框架应用四 - 第一个页面
我们来看一下CI4框架的默认页面是如何实现的. 我们先来认识一下路由文件(app\Config\Routes.php),这个文件非常重要,且功能强大,它定义了URL模式及响应处理方法,我们先看一下这个 ...