原子变量 java_Java原子变量详解
实现全局自增id最简单有效的方式是什么? java.util.concurrent.atomic 包定义了一些常见类型的原子变量。这些原子变量为我们提供了一种操作单一变量无锁( lock-free )的线程安全( thread-safe )方式。实际上该包下面的类为我们提供了类似 volatile 变量的特性,同时还提供了诸如 boolean compareAndSet(expectedValue, updateValue) 的功能。不使用锁实现线程安全听起来似乎很不可思议,这其实是通过CPU的compare and swap指令实现的,由于硬件指令支持当然不需要加锁了。
先不去讨论这些细节,我们来看一下原子变量的用法。一个典型的用法是可以使用原子变量轻松实现全局自增id,就像下面这样:
// 线程安全的序列id生成器
class Sequencer {
private final AtomicLong sequenceNumber = new AtomicLong(0);
publiclongnext() {
return sequenceNumber.getAndIncrement();
}
}
上述代码利用AtomicLong创建了一个Sequencer类,不断调用该类的next()方法就可以得到线程安全的自增id,用起来非常简单直观。下面我们给出每种原子变量类型的用法说明。
AtomicInteger and AtomicLong
AtomicInteger 和 AtomicLong 分别代表原子类型的整型和长整型,这两个类提供十分相似的功能,仅仅是位宽不同。如上例所示,原子整型可用于多线程下全局自增id,除此之外还提供了原子 比较-赋值 等操作,诸如 compareAndSet(expect, update) , decrementAndGet() , getAndDecrement() , getAndSet(newValue) 等等,更全面的接口描述可参考JDK文档。需要提醒的是这些函数都是通过原子CPU指令实现,执行效率较高。
原子整型看似跟普通整型( Integer, Long )类型相似,但不能使用原子整型替代普通整型,因为原子整型是可变的,而普通整型不可变。由于这个原因,使用原子整型作为Map的key并不是个好主意。
你可能会想当然的以为应该有 AtomicFloat 和 AtomicDouble ,遗憾的是类库里并没有这两个类型, AtomicByte 和 AtomicShort 也没有。如果需要替代方案是使用 AtomicInteger 和 AtomicLong 。可通过 Float.floatToRawIntBits(float) 和 Float.intBitsToFloat(int) 将Float存储到 AtomicInteger 中,类似的Double类型也可以存储到 AtomicLong 中。
AtomicReference
AtomicReference 用于存放一个可以原子更新的对象引用。该类包含 get() , set() , compareAndSet() , getAndSet() 等原子方法来获取和更新其代表的对象引用。
AtomicXXXArray
atomic包下面有三种原子数组: AtomicIntegerArray , AtomicLongArra , AtomicReferenceArray ,分别代表整型、长整型和引用类型的原子数组。原子数组使得我们可以线程安全的方式去修改和访问数组里的单个元素。简单示例如下:
// 原子数组示例
AtomicLongArray longArray = new AtomicLongArray(10);// 创建长度为10的原子数组
longArray.set(1, 100);
long v = longArray.getAndIncrement(1);
AtomicReferenceArray referenceArray = new AtomicReferenceArray<>(16);
referenceArray.set(3, "love");
referenceArray.compareAndSet(3, "love", "you");
简单来说原子数组就是一种支持线程安全的数组,仍然具有数组“定长”的性质,如果访问元素超过了数组的长度,将会抛出 IndexOutOfBoundsException 。你可能已经想到了,可以使用线程安全的容器来避免容量不足,我们会在后续章节介绍。
什么是线程安全?
线程安全是指多线程访问是时,无论线程的调度策略是什么,程序能够正确的执行。导致线程不安全的一个原因是状态不一致,如果线程A修改了某个共享变量(比如给id++),而线程B没有及时知道,就会导致B在错误的状态上执行,结果的正确性也就无法保证。原子变量为我们提供了一种保证单个状态一致的简单方式,一个线程修改了原子变量,另外的线程立即就能看到,这比通过锁实现的方式效率要高;如果要同时保证多个变量状态一致,就只能使用锁了。
欢迎加入学习交流群569772982,大家一起学习交流。
原子变量 java_Java原子变量详解相关推荐
- python中的class怎么用_对python 中class与变量的使用方法详解
python中的变量定义是很灵活的,很容易搞混淆,特别是对于class的变量的定义,如何定义使用类里的变量是我们维护代码和保证代码稳定性的关键. #!/usr/bin/python #encoding ...
- python中class变量_对python 中class与变量的使用方法详解
python中的变量定义是很灵活的,很容易搞混淆,特别是对于class的变量的定义,如何定义使用类里的变量是我们维护代码和保证代码稳定性的关键. #!/usr/bin/python #encoding ...
- Java中的宏变量,宏替换详解。
转载自 Java中的宏变量,宏替换详解. 群友在微信群讨论的一个话题,有点意思,特拿出来分享一下. 输出true false 来看下面这段程序,和群友分享的大致一样. public static vo ...
- python定义静态变量_对Pyhon实现静态变量全局变量的方法详解
python不能像C++一样直接定义一个static变量或者通过extern来导入别的库的变量而实现数据共享,但是python的思想是通过模块化来解决这个问题,就是通过模块来实现全局变量. 首先新建一 ...
- R语言 | xlsx包的安装(附链接:java环境变量的配置与详解)
在下载xlsx包之前,要先下载java并且完成环境变量的设置 详细的教程见:(7条消息) java环境变量 的配置与详解(全网最详细教程)_S-D-C-L-Yourn的博客-CSDN博客_java环境 ...
- 条件变量pthread_cond_wait()和pthread_cond_signal()详解
条件变量 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起:另一个线程使"条件成立&qu ...
- java 变量与常量_详解Java变量与常量
一.常量 用final修饰(也称最终变量) 常量在声明时必须赋初值,赋值后不能再修改值 常量名通常用全大写字母表示 声明时需要添加final或static final类型修饰符,例如: private ...
- linux sed p变量,Linux sed 命令详解系列教程之各种问题解决
本文目录: 1 sed中使用变量和变量替换的问题 2 反向引用失效问题 3 "-i"选项的文件保存问题 4 贪婪匹配问题 5 sed命令"a"和"N& ...
- python变量定义大全_详解python变量与数据类型
这篇文章我们学习 Python 变量与数据类型 变量 变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念,变量可以通过变量名访问.在 Python 中 变量命名规定,必须是大小写英文,数字 ...
最新文章
- 换脸火了,我用 Python 快速入门生成模型
- Spring学习五(JDBC支持)
- Leetcode 98. 验证二叉搜索树 解题思路及C++实现
- SQL中EXISTS的使用
- 实现Profile购物车的匿名用户迁移
- 密码强弱提示(27)
- 未捕获typeerror: $形象。cropper不是函数_没有学不会的python--细说自定义函数的细节...
- 【转】Log4Net五步走
- 今天又啃了一些數據類型的東西~漸漸地記起了一些東西。
- CICS的临时存储队列操作
- JAVA小白启蒙篇:第一个SSM框架搭建示例(附源码下载)
- 神经网络与深度学习-吴岸城
- 数据清洗之 数据整理
- 打砖块 java_java实现打砖块小游戏
- EXCEL2016设置下拉选项,图文说明
- 赛格威机器人待遇_赛格威机器人:泊车助理只是应用之一,开发者计划让机器人有无限可能...
- CSS中常用选择器总结
- QQ空间迁移_【Frame_relay子接口的两种配置方法】
- PandoraBox登录无法后台,出现/usr/lib/lua/luci/dispatcher.lua:461(2021-12-19亲测)
- 市场调研报告-全球与中国熔接器市场现状及未来发展趋势