JUC_Striped64

news/2024/11/7 20:46:26/

Striped64 是一个抽象类,继承了 Number 类。它是 Java 并发包中的一部分,用于支持多线程环境下的原子性操作。

Striped64 中,使用 int 数组 baseCounterCell 数组 cells 来存储计数器的值。其中,base 数组存储未被分配到 CounterCell 的线程的计数器值,而 cells 数组则存储已经被分配到 CounterCell 的线程的计数器值。通过使用数组来存储计数器值,可以减少锁的竞争,从而提高并发性能。

Striped64 实现了一些基本的原子操作,例如加、减、乘、除等。它内部实现使用了无锁算法(CAS),保证了操作的原子性和线程安全性。

Number 是 Java 中的一个抽象类,它是所有数字类型的父类,包括整数类型和浮点类型。Number 中定义了一系列抽象方法,包括将数字转换为特定数据类型的方法,例如 intValue()longValue()floatValue()doubleValue() 等。

由于 Striped64 继承了 Number 类,因此它也具有将数字转换为特定类型的方法,可以方便地将计数器的值转换为 int、long、float 或 double 类型。

示例代码:

java
import java.util.concurrent.atomic.AtomicInteger;public abstract class Striped64 extends Number {private static final long serialVersionUID = -1182697631144950088L;// base 数组用于存储未分配到 CounterCell 的线程的计数器值volatile long base;// cells 数组用于存储已经分配到 CounterCell 的线程的计数器值volatile transient CounterCell[] cells;// 使用无锁算法添加 delta 到 base 或 cells 中指定下标的计数器值final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) {int h;if ((h = getProbe()) == 0) {ThreadLocalRandom.current(); // 强制初始化 ThreadLocalRandomh = getProbe();wasUncontended = true;}boolean collide = false; // 如果 hash 冲突,即当前线程在 cells 中对应的元素已被占用,值为 truefor (;;) {CounterCell[] as;CounterCell a;int n;long v;if ((as = cells) != null && (n = as.length) > 0) {if ((a = as[(n - 1) & h]) == null) {if (cellsBusy == 0) { // 当前没有其他线程修改 cells 数组,尝试为当前线程分配 CounterCellCounterCell r = new CounterCell(x);if (cellsBusy == 0 && casCellsBusy()) { // 成功获取 cellsBusy 锁boolean created = false;try {CounterCell[] rs;int m, j;if ((rs = cells) != null && (m = rs.length) > 0&& rs[j = (m - 1) & h] == null) { // 仍然没有其他线程修改 cells 数组,将 CounterCell 设置到 cells 数组中rs[j] = r;created = true;}} finally {cellsBusy = 0;}if (created) {break;}continue; // 竞争失败,继续循环}}collide = false;} else if (!wasUncontended) {wasUncontended = true;} else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) { // 使用 CAS 更新计数器值break;} else if (n >= NCPU || cells != as) { // 由于 hash 冲突,在 cells 中对应的元素已被占用,尝试随机获取一个空闲的元素collide = false;} else if (!collide) { // 记录当前线程在 cells 数组中对应的元素已被占用collide = true;} else if (cellsBusy == 0 && casCellsBusy()) { // 成功获取 cellsBusy 锁try {if (cells == as) { // double checkCounterCell[] rs = new CounterCell[n << 1];for (int i = 0; i < n; ++i) {rs[i] = as[i];}cells = rs;}} finally {cellsBusy = 0;}collide = false;continue; // 竞争失败,继续循环}h = advanceProbe(h);} else if (cellsBusy == 0 && cells == as && casCellsBusy()) { // 成功获取 cellsBusy 锁boolean init = false;try {if (cells == as) { // double checkCounterCell[] rs = new CounterCell[2];rs[h & 1] = new CounterCell(x);cells = rs;init = true;}} finally {cellsBusy = 0;}if (init) {break;}} else if (casBase(v = base, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) { // 通过 CAS 更新 base 中的计数器值break;}}}// 获取当前线程对应的 hash 值,用于将计数器添加到 cells 数组中指定下标的位置static final int getProbe() {return UNSAFE.getInt(Thread.currentThread(), PROBE);}// 随机化当前线程的 hash 值,用于避免不同线程的索引值冲突static final int advanceProbe(int probe) {probe ^= probe << 13; // xorshiftprobe ^= probe >>> 17;probe ^= probe << 5;UNSAFE.putInt(Thread.currentThread(), PROBE, probe);return probe;}// AtomicLong 中用于控制对 cells 数组的竞争static final long CELLSBUSY = 0x00000000L;volatile long cellsBusy;// 获取对 cells 数组的独占锁,避免多线程修改 cells 数组时发生竞争final boolean casCellsBusy() {return UNSAFE.compareAndSwapLong(this, CELLSBUSY, 0, 1);}// 计算集合中所有 CounterCell 的值的总和final long sumCells() {CounterCell[] as = cells;long sum = base;if (as != null) {int n = as.length;for (int i = 0; i < n; ++i) {CounterCell a = as[i];if (a != null) {sum += a.value;}}}return sum;}
}// 定义 CounterCell 类,用于存储已经被分配到的线程的计数器值
class CounterCell {private static final Unsafe UNSAFE;private static final long valueOffset;static {try {UNSAFE = getUnsafe();Class<?> ak = CounterCell.class;valueOffset = UNSAFE.objectFieldOffset(ak.getDeclaredField("value"));} catch (Exception e) {throw new Error(e);}}// 使用 CAS 更新计数器值final boolean cas(long cmp, long val) {return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);}volatile long value;CounterCell(long x) {value = x;}// Unsafe 相关操作private static Unsafe getUnsafe() {try {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);return (Unsafe) theUnsafe.get(null);} catch (Exception e) {throw new Error(e);}}
}

在上述代码中,Striped64 实现了 longAccumulate 方法,用于实现多线程环境下的原子操作。其中使用了无锁算法(CAS)来保证线程安全,并且继承自 Number 类,具有将计数器值转换为各种数值类型的方法。另外,定义了 CounterCell 类,用于存储已经被分配到的线程的计数器值。


http://www.ppmy.cn/news/178960.html

相关文章

线程并发库

Java 5 添加了一个新的包到 Java 平台&#xff0c;java.util.concurrent 包。这个包包含有一系列能够让 Java 的并发 编程变得更加简单轻松的类。在这个包被添加以前&#xff0c;你需要自己去动手实现自己的相关工具类。下面带你认识下 java.util.concurrent包里的这些类&…

HarmoneyOS ArkUI--基础组件

常用基础组件 1 组件介绍 组件&#xff08;Component&#xff09;是界面搭建与显示的最小单位&#xff0c;HarmonyOS ArkUI声明式开发范式为开发者提供了丰富多样的UI组件&#xff0c;我们可以使用这些组件轻松的编写出更加丰富、漂亮的界面。 组件根据功能可以分为以下五大类…

了解一场棒球团建设活动·棒球1号位

一场棒球团建活动策划&#xff1a; 1. 活动概述&#xff1a; 这是一场棒球团建活动&#xff0c;旨在通过这个活动来促进团队合作、增强团队精神&#xff0c;并提升员工的体育素质和承压能力。 2. 活动时间和地点&#xff1a; 时间&#xff1a;一个周末的上午或下午 地点&am…

DiffRate详解:高效Vision Transformers的可微压缩率

DiffRate详解&#xff1a;高效Vision Transformers的可微压缩率 0. 引言1. 相关内容介绍1.1 Transformer Block1.2 令牌修剪和合并1.3 修剪和合并的统一 2 DiffRate中的创新点2.1 令牌排序2.2 压缩率重参数化2.3 训练目标 3. 算法流程4. 总结 0. 引言 就当前的Vision Transfor…

【Linux网络服务】Nginx优化

Nginx网页优化 一、配置Nginx网页缓存时间1.1设置方法 二、隐藏Nginx版本号2.1方法一&#xff1a;修改配置文件2.2方法二&#xff1a;修改源码文件&#xff0c;重新编译 三、修改用户与组四、日志切割五、连接超时六、更改进程数七、网页压缩八、配置防盗链九、Linux内核参数优…

PHP快速实战19-PHP使用IMAP获取QQ邮箱的收件列表及内容

文章目录 前言关于IMAP协议安裝与实现步骤1&#xff1a;安装IAMP扩展1.1 检查IMAP是否已安装1.2 安装IMAP扩展1.3 启用IMAP扩展1.4 重启服务 步骤2&#xff1a;开始功能实现2.1 开始编码2.2 代码执行 常见的20个PHP中IMAP方法总结 前言 本文已收录于PHP全栈系列专栏&#xff1…

DNS是什么?DNS攻击有哪些?“诈骗集团”?

DNS是什么&#xff1f; DNS&#xff08;Domain Name System&#xff09;是互联网上的一种分布式命名系统&#xff0c;用于将易记的域名&#xff08;如www.example.com&#xff09;映射到对应的IP地址&#xff08;如192.0.2.1&#xff09;。它充当了互联网上的电话簿&#xff0…

【Collection集合的遍历】

Collection集合的遍历 Iterator&#xff1a;迭代器是集合的专用的遍历的方式&#xff0c;使用时也需要导包 Iterator iterator()&#xff1a;返回集合中元素的迭代器&#xff0c;通过集合的iterator()方法得到迭代器使用过集合的iterator()方法得到的&#xff0c;所以说它是依…