因为当需要进行原子限定的属性所属的类会被创建大量的实例对象,如果用AtomicLong每个实例里面都要创建AtomicLong对象,从而多出内存消耗,显然是不合适的。
因此出现了AtomicLongFieldUpdater(原子字段更新器),仅需要在抽象的父类中声明一个静态的更新器,就可以在各个对象中使用了。
AtomicLongFieldUpdater:
-
基于反射的实用工具,可以对指定类的指定volatile字段进行原子更新。
volatile:
-
声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步,
-
因此不会将该变量上的操作与其他内存操作一起重排序。
-
volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。
-
volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多"内存屏障"指令来保证处理器不发生乱序执行。
-
内存屏障:
-
指令重排序时不能把后面的"指令重排序"到内存屏障之前的位置
-
指令重排序:
-
指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理
代码:
package com.zr.concurrency.test;
import com.zr.concurrency.annotation.ThreadSafe;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
/**
* @description: 为什么有了AtomicLong还要使用AtomicLongFieldUpdater
* 因为当需要进行原子限定的属性所属的类会被创建大量的实例对象,如果用AtomicLong,每个实例里面都要创建AtomicLong对象,从而多出内存消耗.显然是不合适的。
* 因此出现了AtomicLongFieldUpdater(原子字段更新器),仅需要在抽象的父类中声明一个静态的更新器,就可以在各个对象中使用了。
* AtomicLongFieldUpdater:
* 基于反射的实用工具,可以对指定类的指定volatile字段进行原子更新。
* volatile:
* 声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步,
* 因此不会将该变量上的操作与其他内存操作一起重排序。
* volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。
* volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多"内存屏障"指令来保证处理器不发生乱序执行。
* 内存屏障:
* 指令重排序时不能把后面的"指令重排序"到内存屏障之前的位置
* 指令重排序:
* 指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理
* @author: liangrui
* @create: 2019-12-29 22:01
**/
@Slf4j
@ThreadSafe
public class ConcurrencyTest3 {
//原子操作类
private static AtomicLongFieldUpdater<ConcurrencyTest3> updater=AtomicLongFieldUpdater.newUpdater(ConcurrencyTest3.class,"count");
//原子变量,使用volatile修饰,不能使用static修饰
@Getter
private volatile long count=100;
public static void main(String[] args) {
ConcurrencyTest3 concurrencyTest3=new ConcurrencyTest3();
//如果concurrencyTest3中的count等于100,则更新count为120,返回true
if (updater.compareAndSet(concurrencyTest3,100,120)){
//输出更新后的count
log.info("update success,count: {}",concurrencyTest3.getCount());
}else {
//更新失败,输出count
log.info("update failed,count: {}",concurrencyTest3.getCount());
}
//此时count等于120,所以会返回false
if (updater.compareAndSet(concurrencyTest3,100,120)){
//输出更新后的count
log.info("update success,count: {}",concurrencyTest3.getCount());
}else {
//更新失败,输出count
log.info("update failed,count: {}",concurrencyTest3.getCount());
}
}
}
执行结果:
22:32:47.100 [main] INFO com.zr.concurrency.test.ConcurrencyTest3 - update success,count: 120
22:32:47.106 [main] INFO com.zr.concurrency.test.ConcurrencyTest3 - update failed,count: 120