Java模拟简单的CAS实现

这篇文章主要模拟CPU的CAS实现,详细的实现原理都加上注释了,不一一解释了。当然这不是真正的CAS实现,真正的CAS是CPU指令来实现的。

Compare And Swap(CAS)

CAS的原理是拿期望的值和原本的一个值作比较,如果相同则更新为新的值。反之,会继续拿期望的值与原本的值作比较,知道成功为止。


模拟CAS实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.lang.reflect.Field;

/**
* 简单模拟CAS实现
* Created by Evai ON 1/3/18.
*/
public class SimulatedCAS {
/**
* 原始值
*/
private long valueOffset;

/**
* 修改原始值
* @param o 需要修改的对象
* @param offset 需要修改的值
*/
public void setValueOffset(Object o, long offset) {
setField(o, offset);
}

/**
* 获取原始值
* @return
*/
public long getValueOffset() {
return valueOffset;
}

/**
* 如果原始值和预期值相等,更新原始值及对象的value值,这里加了同步锁,模拟CAS原子操作
* @param o 需要修改的对象
* @param expect 预期值
* @param update 更新值
* @return
*/
public synchronized boolean compareAndSwap(Object o, long expect, long update) {
return getValueOffset() == expect && setField(o, update);
}

/**
* 修改原始值及对象的value值
* @param o 需要修改的对象
* @param update 更新值
* @return
*/
private boolean setField(Object o, long update) {
long oldValue = getValueOffset();//存储旧的原始值
this.valueOffset = update;//更新为新值
try {
//获取对象上的value属性
Field field = o.getClass().getDeclaredField("value");
//设置该属性可访问权限
field.setAccessible(true);
//旧值更新
field.set(o, update);
return true;
} catch (Exception e) {
this.valueOffset = oldValue;//失败回滚原始值
throw new Error("更新值失败", e);
}
}

}

模拟AtomicLong实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* 简单模拟AtomicLong实现
* Created by Evai ON 1/3/18.
*/
public class AtomLong {
private static final SimulatedCAS cas = new SimulatedCAS();
private volatile long value;

public AtomLong() {}

public AtomLong(long v) {
//实例化类后更新value值及原始值
cas.setValueOffset(this, v);
}

public long get() {
return value;
}

/**
* 类似 ++i
* @return
*/
public long incrementAndGet() {
return getAndAddLong(1L) + 1L;
}

/**
* 类似 i++
* @return
*/
public long getAndIncrement() {
return getAndAddLong(1L);
}

/**
* 类似 --i
* @return
*/
public long decrementAndGet() {
return getAndAddLong(-1L) - 1L;
}

/**
* 类似 i--
* @return
*/
public long getAndDecrement() {
return getAndAddLong(-1L);
}

/**
* 获取到当前value值(即期望值),如果期望值和原始值相等,返回value,反之继续获取最新的value值,循环直到相等为止
* @param delta 增减量
* @return
*/
private long getAndAddLong(long delta) {
long v;
do {
v = get();//获取当前最新的value值
} while (!cas.compareAndSwap(this, v, v + delta));

return v;
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* Created by Evai ON 1/3/18.
*/
public class CASCounter {
private static final AtomLong casLong = new AtomLong(1);
private static final long LIMIT = 100;

private static void incrementLong() {
try {
while (casLong.get() < LIMIT) {
Thread.sleep(100);
if (casLong.get() < LIMIT) {
System.out.println(Thread.currentThread().getName() + ": " + casLong.getAndIncrement());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
incrementLong();
}
}).start();
}
}

}