Java中CAS详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Java中CAS详解
⾸先我们要了解Java内存模型(Java Memory Model)。

JMM就是⼀套规范,描述了Java线程对变量的访问规则。

⾸先,在jvm中有⼀个main memory,⽽每个线程都有⾃⼰的working memory,⼀个线程对⼀个variable进⾏操作的时候,会先在⾃⼰的working memory⾥⾯建⽴⼀个copy,操作完成之后再写⼊main memory,如果有多个线程同时操作同⼀个variable,就可能会出现不可预知的结果,所以线程安全就是为了避免这种情况的发⽣。

volatile是不错的机制,volatile关键字作⽤:1.volatile可以保证变量的可见性。

2.保证有序性。

(防⽌指令重排)。

【当⼀个线程修改了共享变量的值,新的值会⽴刻同步到主内存当中。

⽽其他线程读取这个变量的时候,也会强制从主内存中拉取最新的变量值。

】但是volatile 不能保证原⼦性。

因此对于同步最终还是要回到锁机制上来。

在java中,确保线程安全的⽅法有两种:⼀种是使⽤内置锁(synchronized),⼀种是使⽤原⼦类(java.util.concurrent包下的),对于原⼦类,它所⽤的机制就是CAS机制。

什么是CAS?
CAS:Compare and Swap,即⽐较再交换。

jdk5增加了并发包java.util.concurrent.*,其下⾯的类使⽤CAS算法实现了区别于synchronouse同步锁的⼀种乐观锁。

JDK 5之前Java语⾔是靠synchronized关键字保证同步的,这是⼀种独占锁,也是是悲观锁。

CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。

如果内存位置的值与预期原值相匹配,那么处理器会⾃动将该位置值更新为新值。

否则,处理器不做任何操作。

CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。

”CAS是通过⽆限循环来获取数据的,若果在第⼀轮循环中,a线程获取地址⾥⾯的值被b线程修改了,那么a线程需要⾃旋,到下次循环才有可能机会执⾏。

通常将 CAS ⽤于同步的⽅式是从地址 V 读取值 A,执⾏多步计算来获得新值 B,然后使⽤ CAS 将 V 的值从 A 改为 B。

如果 V 处的值尚未同时更改,则 CAS 操作成功。

利⽤CPU的CAS指令,同时借助JNI来完成Java的⾮阻塞算法。

其它原⼦操作都是利⽤类似的特性完成的。

⽽整个J.U.C都是建⽴在CAS之上的,因此对于synchronized阻塞算法,J.U.C在性能上有了很⼤的提升。

现代cpu提供了特殊的指令,可以⾃动更新共享数据,⽽且能够检测到其他线程的⼲扰,⽽compareAndSet()就是⽤这些代替了锁定,compareAndeSet()是调⽤本地⽅法来完成cpu指令的操作。

来看看AutomicInteger的源码:
private volatile int value;//毫⽆疑问,没有锁的机制下,必须借助volatile保证线程间的数据可见性
public final int get(){
return value;
}
// 来看看++i是怎么实现的:
public final int increamentAndGet(){
for(;;){ // ⽆限循环来获取数据
int current = get();
int next = current + 1;
if(compareAndSet(current,next))
return next;
}
}
由此可见,AtomicInteger.incrementAndGet的实现⽤了乐观锁技术,调⽤了类sun.misc.Unsafe库⾥⾯的 CAS算法,⽤CPU指令来实现⽆锁⾃增。

所以,AtomicInteger.incrementAndGet的⾃增⽐⽤synchronized的锁效率倍增。

相关文档
最新文档