《Java并发编程的艺术》读后笔记-Java中的13个原子操作类(第七章)

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

Unsafe的源码如下:

/**

  • 如果当前数值是expected,则原子的将Java变量更新成x

  • @return 如果更新成功则返回true

*/

public final native boolean compareAndSwapObject(Object o,

long offset,

Object expected,

Object x);

public final native boolean compareAndSwapInt(Object o, long offset,

int expected,

int x);

public final native boolean compareAndSwapLong(Object o, long offset,

long expected,

long x);

通过代码,我们发现Unsafe只提供了3种CAS方法:compareAndSwapObjectcompareAndSwapIntcompareAndSwapLong

再看AtomicBoolean源码,发现它是先把Boolean转换成整型,再使用compareAndSwapInt进行CAS,所以原子更新char、float和double变量也可以用类似的思路来实现。

2.原子更新数组


通过原子的方式更新数组里的某个元素Atomic包提供了以下4个类:

  1. AtomicIntegerArray:原子更新整型数组里的元素。

  2. AtomicLongArray:原子更新长整型数组里的元素。

  3. AtomicReferenceArray:原子更新引用类型数组里的元素。

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

  • int addAndGet(int i,int delta):以原子方式将输入值与数组中索引i的元素相加。

  • boolean compareAndSet(int i,int expect,int update):如果当前值等于预期值,则以原子方式将数组位置i的元素设置成update值。

以上几个类提供的方法几乎一样,所以本节仅以AtomicIntegerArray为例进行讲解。

AtomicIntegerArray的使用实例代码:

/**

  • @author xppll

  • @date 2022/1/14 18:22

*/

public class AtomicIntegerArrayTest {

static int[] value = new int[]{1, 2};

static AtomicIntegerArray ai = new AtomicIntegerArray(value);

public static void main(String[] args) {

ai.getAndSet(0, 3);

System.out.println(ai.get(0));//3

System.out.println(value[0]);//1

}

}

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

3.原子更新引用类型


原子更新基本类型的AtomicInteger,只能更新一个变量,如果要原子更新多个变量,就需要使用这个原子更新引用类型提供的类Atomic包提供了以下3个类:

  1. AtomicReference:原子更新引用类型。

  2. AtomicReferenceFieldUpdater:原子更新引用类型里的字段。

  3. AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子更新一个布尔类型的标记位和引用类型。构造方法是AtomicMarkableReference(V initialRef,boolean initialMark)。

以上几个类提供的方法几乎一样,所以本节仅以AtomicReference为例进行讲解。

AtomicReference的使用示例代码:

/**

  • @author xppll

  • @date 2022/1/14 17:23

*/

public class AtomicReferenceTest {

public static AtomicReference atomicReference = new AtomicReference();

public static void main(String[] args) {

User user = new User(“xpp”, 20);

atomicReference.set(user);

User updateUser = new User(“updateXpp”, 24);

atomicReference.compareAndSet(user, updateUser);

System.out.println(atomicReference.get().getName());//updateXpp

System.out.println(atomicReference.get().getOld());//24

}

static class User {

private String name;

private int old;

public User(String name, int old) {

this.name = name;

this.old = old;

}

public String getName() {

return name;

}

public int getOld() {

return old;

}

}

}

代码中首先构建一个user对象,然后把user对象设置进AtomicReferenc中,最后调用compareAndSet方法进行原子更新操作,实现原理同AtomicInteger里的compareAndSet方法。

4.原子更新字段类


如果需原子地更新某个类里的某个字段时,就需要使用原子更新字段类Atomic包提供了以下3个类进行原子字段更新:

  1. AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。

  2. AtomicLongFieldUpdater:原子更新长整型字段的更新器。

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

要想原子地更新字段类需要两步。

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

  2. 第二步,更新类的字段(属性)必须使用public volatile修饰符。

AstomicIntegerFieldUpdater代码演示:

/**

  • @author xppll

  • @date 2022/1/14 17:46

*/

public class AtomicIntegerFieldUpdaterTest {

//创建原子更新器,并设置需要更新的对象类和对象的属性

private static AtomicIntegerFieldUpdater a =

AtomicIntegerFieldUpdater.newUpdater(User.class, “old”);

public static void main(String[] args) {

//开始xpp的年龄

User xpp = new User(“xpp”, 10);

//长了一岁,这里输出还是旧的年龄

System.out.println(a.getAndIncrement(xpp));//10

//输出xpp现在的年龄

System.out.println(a.get(xpp));//11

}

public static class User {

private String name;

//需要更新的字段必须使用public volatile修饰符

public volatile int old;

public User(String name, int old) {

this.name = name;

this.old = old;

}

public String getName() {

return name;

}

public int getOld() {

最后

小编利用空余时间整理了一份《MySQL性能调优手册》,初衷也很简单,就是希望能够帮助到大家,减轻大家的负担和节省时间。

关于这个,给大家看一份学习大纲(PDF)文件,每一个分支里面会有详细的介绍。

image

这里都是以图片形式展示介绍,如要下载原文件以及更多的性能调优笔记(MySQL+Tomcat+JVM)!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

public int getOld() {

最后

小编利用空余时间整理了一份《MySQL性能调优手册》,初衷也很简单,就是希望能够帮助到大家,减轻大家的负担和节省时间。

关于这个,给大家看一份学习大纲(PDF)文件,每一个分支里面会有详细的介绍。

[外链图片转存中…(img-0cjhK7Ff-1714686009397)]

这里都是以图片形式展示介绍,如要下载原文件以及更多的性能调优笔记(MySQL+Tomcat+JVM)!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值