博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java并发--Java中的13个原子操作类详解
阅读量:2442 次
发布时间:2019-05-10

本文共 3945 字,大约阅读时间需要 13 分钟。

原子操作类

Java从JDK1.5开始,提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。

因为变量有很多种,所以在Atomic包里一共提供了13个类(基本都是Unsafe实现的包装类),属于4种类型的原子更新方式,分别为:

  • 原子更新基本类型
  • 原子更新数组
  • 原子更新引用
  • 原子更新属性(字段)

原子更新基本类型

  • AtomicBoolean: 原子更新布尔类型
  • AtomicInteger: 原子更新整型
  • AtomicLong: 原子更新长整型

以上3个类提供的方法几乎一样,以AtomicInteger为例:

方法 描述
int addAndGet(int delta) 以原子方式将输入和数值与实例中的值(AtomicInteger里的value)相加,并返回结果。
boolean compareAndSet(int expect, int update) 如果输入的数值等于预期值,则以原子方式将该值设置为输入的值。
int getAndIncrement() 以原子方式将当前值加1,注意,这里返回的是自增前的值
void lazySet(int newValue) 最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一小段时间内还是可以读取到旧的值。
int getAndSet(int newValue) 以原子方式设置为newValue的值,并返回旧值。

示例:

public class AtomicIntegerTest {
public static void main(String[] args) {
AtomicInteger ai = new AtomicInteger(1); System.out.println(ai.getAndIncrement()); System.out.println(ai.get()); }}

输出:

12

原子更新数组

  • AtomicIntegerArray: 原子更新整型数组里的元素
  • AtomicLongArray: 原子更新长整型数组里的元素
  • AtomicReferenceArray: 原子更新引用类型数组里的元素

以上几个类提供的方法几乎一样,以AtomicIntegerArray为例:

AtomicIntegerArray主要提供原子的方式更新数组里的整型,常用方法如下:

  • int addAndGet(int i, int delta): 以原子方式将输入值与数组中索引i的元素相加。
  • boolean compareAndSet(int i, int expect, int update): 如果当前值等于预期值,则以原子方式将数组位置i的元素设置成update值。

示例:

public class AtomicIntegerArrayTest {
public static void main(String[] args) {
int[] arr = new int[]{
1, 2, 3}; AtomicIntegerArray aia = new AtomicIntegerArray(arr); aia.getAndSet(0, 3); System.out.println(aia.get(0)); System.out.println(arr[0]); }}

输出:

31

需要注意的是,数组arr通过构造方法传递进去,然后AtomicIntegerArray会讲当前数组复制一份,所以当AtomicIntegerArrayList对内部的数组元素进行丢改时,不会影响传入的数组。

原子更新引用类型

  • AtomicReference: 原子更新引用类型
  • AtomicReferenceFieldUpdater: 原子更新引用类型里的字段
  • AtomicMarkableReference: 原子更新带有标记位的引用类型。可以原子更行一个布尔类型的标记位和引用类型。
    构造方法为:AtomicMarkableReference(V initialRef, boolean initiaMark)

以AtomicReference为例:

public class AtomicReferenceTest {
public static void main(String[] args) {
AtomicReference
arf = new AtomicReference
(); User user = new User("tom", 18); arf.set(user);//传入引用 User updateUser = new User("TOM", 88); arf.compareAndSet(user, updateUser);//比较,如果一致,就更新。 System.out.println(arf.get().getName()); System.out.println(arf.get().getAge()); }}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; }}

首先构建一个user对象,然后把user对象设置进AtomicReference中,最后调用compareAndSet方法进行原子更新操作。

输出:

TOM88

原子更新字段类

  • AtomicIntegerFieldUpdater: 原子更新整型的字段的更新器
  • AtomicLongFieldUpdater: 原子更新长整型字段的更新器
  • AtomicStampedReference: 原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更新数据和数据的版本号,可以解决使用CAS进行原子更新时可能出现的ABA问题。

想要原子更新字段需要两步:

  • 第一步:因为原子更细字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater() 创建一个更新器,并且需要设置想要更新的类和属性。
  • 第二步:更新类的字段(属性)必须使用public volatile 修饰。

以上3个类提供的方法几乎一样,所以以AtomicIntegerFieldUpdater为例:

package pers.zhang.atomic;import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;/** * @author zhang * @date 2020/1/17 - 15:38 */public class AtomicIntegerFieldUpdaterTest {
public static void main(String[] args) {
//创建原子更新器,并设置需要更新的对象和属性 AtomicIntegerFieldUpdater
aifu = AtomicIntegerFieldUpdater.newUpdater(User.class, "age"); //设置tom为10岁 User user = new User("tom", 10); //tom长了一岁,但是仍输出旧的年龄 System.out.println(aifu.getAndIncrement(user)); //输出tom现在的年龄 System.out.println(aifu.get(user)); } public static class User{
public volatile 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; } }}

输出:

1011

转载地址:http://sypqb.baihongyu.com/

你可能感兴趣的文章
ipad和iphone适配_如何在iPhone和iPad上调节音乐均衡器
查看>>
USB 4将以更少的钱带来Thunderbolt的速度
查看>>
windows 延迟 启动_如何禁用Windows 10启动延迟
查看>>
如何将iPhone语音邮件备份到MP3
查看>>
小米fortnite_如何将Fortnite移到另一个文件夹,驱动器或PC
查看>>
如何使用阴天将在线文件附加到Gmail邮件
查看>>
sway教程_什么是Microsoft Sway,该如何处理?
查看>>
为什么在网上分享生日很危险
查看>>
jieba使用自定义词典_如何在Word 2013中使用自定义词典
查看>>
蓝牙4.1 4.2 5.0_蓝牙5.1:新功能及其重要性
查看>>
FaceTime中存在一个巨大的错误。 立即停用
查看>>
改善智能家居的三种方法
查看>>
小米路由器3g 5g速度_为什么您(可能)不想要5G路由器
查看>>
如何评估和分析好照片
查看>>
如何在iPhone上将GIF设置为动态壁纸
查看>>
如何使F8键在Windows 8中进入安全模式
查看>>
富文本中添加字体选项功能_如何将开发人员选项卡添加到Microsoft Office功能区...
查看>>
如何将音乐添加到PowerPoint演示文稿
查看>>
mozilla.pdf_Mozilla说它没有从Booking.com赚钱
查看>>
Windows 8.1如何在任何地方集成SkyDrive
查看>>