【Java】Java CAS机制,
【Java】Java CAS机制,
1、原子操作类
所谓原子操作类,指的是java.util.concurrent.atomic包下,一系列以Atomic开头的包装类。如AtomicBoolean,AtomicInteger,AtomicLong,它们分别用于Boolean,Integer,Long类型的原子性操作。这里的Atomic操作类的底层正是使用了“CAS机制”。
2、CAS
CAS(Compare and Swap),是比较并替换的意思。
CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。
更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。
3、CAS缺点
(1)并发量较高时CPU开销过大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很到的压力。
(2)只能保证单个变量的原子性
CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。
(3)ABA问题
4、Java语言CAS底层如何实现?
利用unsafe提供了原子性操作方法。以AtomicInteger举例说明:
(1)看AtomicInteger两个方法:
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
(2)看Unsafe的getAndAddInt方法:
/**
* Atomically adds the given value to the current value of a field
* or array element within the given object <code>o</code>
* at the given <code>offset</code>.
*
* @param o object/array to update the field/element in
* @param offset field/element offset
* @param delta the value to add
* @return the previous value
* @since 1.8
*/
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
注意:compareAndSwapInt整个比较并替换的操作是一个原子操作。
/** Volatile version of {@link #getInt(Object, long)} */
public native int getIntVolatile(Object o, long offset);
/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
* @return <tt>true</tt> if successful
*/
public final native boolean compareAndSwapInt(Object o, long offset,
int expected,
int x);
(3)看AtomicInteger的unsafe和valueOffset
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
(4)什么是unsafe呢?
Java语言不像C,C++那样可以直接访问底层操作系统,但是JVM为我们提供了一个后门,这个后门就是unsafe。unsafe为我们提供了硬件级别的原子操作。
至于valueOffset,是通过unsafe.objectFiledOffset方法得到,所代表的是AtomicInteger对象value成员变量在内存中的偏移量。我们可以简单的把valueOffset理解为value变量的内存地址。
正是unsafe的compareAndSwapInt方法保证了Compare和Swap操作之间的原子性操作。
5、什么是ABA问题?怎么解决?
当一个值从A更新成B,又更新回A,普通CAS机制会误判通过检测。
利用版本号比较可以有效解决ABA问题。
真正要做到严谨的CAS机制,我们在compare阶段不仅要比较期望值A和地址V中的实际值,还要比较变量的版本号是否一致。
参考文档:
https://blog.csdn.net/qq_32998153/article/details/79529704
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/sun/misc/Unsafe.java
相关文章
- 暂无相关文章
用户点评