【Java并发】Java中的原子操作类
综述
JDK从1.5开始提供了java.util.concurrent.atomic包。
通过包中的原子操作类能够线程安全地更新一个变量。
包含4种类型的原子更新方式:基本类型、数组、引用、对象中字段更新。
atomic包中的原子操作类基本上内部都是使用Unsafe类实现的,原子更新的实质其实就是获取内存偏移地址,对地址中的变量进行更新。
关于Unsafe类,可以参考我的这篇博文【Java并发】Java中的Unsafe类
1.原子更新基本类型类
atomic包内包含AtomicBoolean、AtomicInteger、AtomicLong这3个类,以下以AtomicInteger进行讲解。
AtomicInteger是如何实现原子操作的?
是使用Unsafe类实现的,而Unsafe实现原子操作的原理是通过得到变量相对于对象示例的内存偏移地址,更新内存地址内的变量值。
下面是摘录的AtomicInteger的部分源码。
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
} /**
* Atomically decrements by one the current value.
*
* @return the previous value
*/
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
} /**
* Atomically adds the given value to the current value.
*
* @param delta the value to add
* @return the previous value
*/
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
} /**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
} /**
* Atomically decrements by one the current value.
*
* @return the updated value
*/
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
} /**
* Atomically adds the given value to the current value.
*
* @param delta the value to add
* @return the updated value
*/
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
2.原子更新数组
atomic包内包含AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray这3个类,以下以AtomicIntegerArray进行讲解。
AtomicIntegerArray是如何实现原子操作的?
是使用Unsafe类实现的,而Unsafe实现原子操作的原理是通过得到变量相对于数组的内存偏移地址,更新内存地址内的变量值。
下面是摘录的AtomicIntegerArray的部分源码。
/**
* Atomically increments by one the element at index {@code i}.
*
* @param i the index
* @return the previous value
*/
public final int getAndIncrement(int i) {
return getAndAdd(i, 1);
} /**
* Atomically decrements by one the element at index {@code i}.
*
* @param i the index
* @return the previous value
*/
public final int getAndDecrement(int i) {
return getAndAdd(i, -1);
} /**
* Atomically adds the given value to the element at index {@code i}.
*
* @param i the index
* @param delta the value to add
* @return the previous value
*/
public final int getAndAdd(int i, int delta) {
return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
} /**
* Atomically increments by one the element at index {@code i}.
*
* @param i the index
* @return the updated value
*/
public final int incrementAndGet(int i) {
return getAndAdd(i, 1) + 1;
} /**
* Atomically decrements by one the element at index {@code i}.
*
* @param i the index
* @return the updated value
*/
public final int decrementAndGet(int i) {
return getAndAdd(i, -1) - 1;
} /**
* Atomically adds the given value to the element at index {@code i}.
*
* @param i the index
* @param delta the value to add
* @return the updated value
*/
public final int addAndGet(int i, int delta) {
return getAndAdd(i, delta) + delta;
}
3.原子更新引用
使用AtomicInteger只能原子更新一个变量,如果要原子更新多个变量,就需要将多个变量封装起来,原子更新对象引用。
atomic包内包含AtomicReference、AtomicReferenceFieldUpdater、AtomicUpdater这3个类,以下以AtomicIntegerArray进行讲解。
下面是摘录的AtomicReference的部分源码。
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
@SuppressWarnings("unchecked")
public final V getAndSet(V newValue) {
return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
}
4.原子更新字段类
用于更新类里的某个字段。
atomic包内包含AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference这3个类。
AtomicStampedReference 将整数值与引用关联起来,可以用于原子地更新数据和数据的版本号,可以解决CAS的ABA问题。
【Java并发】Java中的原子操作类的更多相关文章
- Java中的原子操作类
转载: <ava并发编程的艺术>第7章 当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可 ...
- java并发编程:线程安全管理类--原子操作类--AtomicInteger
在java并发编程中,会出现++,--等操作,但是这些不是原子性操作,这在线程安全上面就会出现相应的问题.因此java提供了相应类的原子性操作类. 1.AtomicInteger
- java中的原子操作类AtomicInteger及其实现原理
/** * 一,AtomicInteger 是如何实现原子操作的呢? * * 我们先来看一下getAndIncrement的源代码: * public final int getAndIncremen ...
- Java并发编程系列-(3) 原子操作与CAS
3. 原子操作与CAS 3.1 原子操作 所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何context switch,也就是切换到另一个线程. 为了实 ...
- Java并发编程中的若干核心技术,向高手进阶!
来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...
- Java并发编程中的相关注解
引自:http://www.cnblogs.com/phoebus0501/archive/2011/02/21/1960077.html Java并发编程中,用到了一些专门为并发编程准备的 Anno ...
- Java并发编程中的设计模式解析(二)一个单例的七种写法
Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ...
- Java并发编程中线程池源码分析及使用
当Java处理高并发的时候,线程数量特别的多的时候,而且每个线程都是执行很短的时间就结束了,频繁创建线程和销毁线程需要占用很多系统的资源和时间,会降低系统的工作效率. 参考http://www.cnb ...
- int是java.lang包中可用的类的名称
int是java.lang包中可用的类的名称(x) int为基本数据类型,不是类
随机推荐
- DB水平切换要点
分区健选择 数据应该怎样拆分,依照什么纬度来拆分 节点路由 应用程序写死/客户端(TDDL,cobar-client)/中间层(cobar-server) 固定分配/动态分配/混合 分片数据均衡 某些 ...
- FOJ 1402(dp推规律)
推规律吧 /** 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
- 深入理解 Java 垃圾回收机制(转)
一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理.由于有个垃圾回收机制 ...
- NATS源代码分析之auth目录
NATS是一个轻量的消息发布-订阅系统.NATS的核心是Event machine. 项目Server端源代码地址: github.com/nats-io/gnatsd 在auth目录中, multi ...
- .Net framework 的浏览器定义文件
.net framework4.5.1之前的版本有一个非常愚蠢的设定, 它为每个浏览器设置了一个浏览器定义文件, 通过正则表达式来匹配浏览器的userAgent, 然后来定义一些功能集. 这种做法有一 ...
- JZOJ.5230【NOIP2017模拟8.5】队伍统计
Description 现在有n个人要排成一列,编号为1->n .但由于一些不明原因的关系,人与人之间可能存在一些矛盾关系,具体有m条矛盾关系(u,v),表示编号为u的人想要排在编号为v的人前面 ...
- Caused by: java.lang.IllegalArgumentException: @EnableAsync annotation metadata was not injected
需要注意的是ComponentScan 不能扫描 org.springframework 否则会报错,要扫描指定的package才行
- matplotlib绘制圆饼图
import matplotlib.pyplot as plt labels = ['Nokia','Samsung','Apple','Lumia'] values = [10,30,45,15] ...
- 巨蟒python全栈开发数据库攻略1:基础攻略
1.什么是数据库? 2.数据库分类 3.数据库简单介绍 4.安装数据库 5.修改root密码 6.修改字符集 7.sql介绍 8.简单sql操作
- 解决scalac Error: bad option -make:transitive
关闭idea 打开项目所在位置并cd .idea 修改scala_compiler.xml文件 删除掉参数行包含-make:transitive 保存后退出编辑并重启idea打开项目