Java多线程----CAS
Posted 结构化思维wz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程----CAS相关的知识,希望对你有一定的参考价值。
CAS
CAS(Compare And Swap)协议/算法是由硬件实现的。
CAS可以将 read - modify -write 这类的操作转换为 原子操作。
i++ 包括三个原子操作:
- 从主内存读取i变量的值
- 对i的值加1
- 再把加一之后的值保存到主内存
CAS原理:
在把数据更新到主内存时,再次读取主内存变量的值,如果现在变量的值与期望的值(操作起始时读取的值)一致就更新。
理想状态:
并发问题可能的状态:
CAS就是把数据更新到主内存的共享变量前,再次读取主内存共享变量的值,如果现在读取的共享变量的值与期望的值一样就更新:
使用CAS实现线程安全的计数器
package se.high.thread.cas;
/**
* @author 王泽
* 使用CAS实现一个线程安全的计数器
*/
public class CasTest {
public static void main(String[] args) {
CASCounter cas = new CASCounter();
for (int i = 0; i < 10000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"----->"+cas.incrementAndGet());
}
}).start();
}
}
}
class CASCounter{
//使用volatile修饰value的值,使线程可见
volatile private long value;
public long getValue(){
return value;
}
private boolean compareAndSwap(long expectedValue,long newValue){
//如果当前value的值与情网的expectedValue值一样,就把当时的Value字段替换为newValue值
synchronized (this){
if (value == expectedValue){
value = newValue;
return true;
}else {
return false;
}
}
}
//定义自增的方法
public long incrementAndGet(){
long oldValue;
long newValue;
do {
oldValue = value;
newValue = oldValue+1;
}while(!compareAndSwap(oldValue,newValue));
return newValue;
}
}
CAS中的ABA问题
CAS实现原子操作背后有一个假设:共享变量的当前值与当前线程提供的期望值相同,就认为这个变量没有被其他线程修改过。
实际上这个假设不一定总成立。
例如:有一个共享变量 count =0,A线程对count的值修改为10,B线程对count修改为20,C线程对count修改为10; 如果当前线程看到count变量的值为10,我们是否认为count变量的值没有被其他线程更新呢??这种结果是否能接受??
共享变量经历了 A -> B -> A 的更新
是否能够接受ABA的问题跟实现算法有关。如果想要规避ABA问题,可以为共享变量引入一个修订号(时间戳),每次修改共享变量时,相应的修订号就会增加1。
[A,0] -> [B,1] -> [A,2]
这也是AtomicStampedReference
类就是基于这种思想产生的。
以上是关于Java多线程----CAS的主要内容,如果未能解决你的问题,请参考以下文章
java多线程 CAS原子引用AtomicReference