cas官方说明:
Compare and Swap,比较并操作,CPU指令,在大多数处理器架构,包括IA32、Space中采用的都是CAS指令,CAS的语义是“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”,CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
cas 是操作系统指令,目前绝大多数处理器使用这个指令架构。
cas 是通过锁cpu 的核的高速缓存或者地址总线(锁地址总线是针对多cpu的分布式系统)实现的。cas 是一套指令。
通过一个cas操作执行一个指令,首先,这一套指令的第一条是要获取目标值放入在对应的缓存中。
cas操作最根本的是针对并发,很多内核或者线程已经同时获取到目标值,接着就是执行操作,然后写回内存。在写回去,又会再一次获取目标值,比对之前记录的目标值是不是一样,一样就基于目标值操作。否则更新目标值,直到目标值比对结果一样,那么就基于最新的目标值操作(不断尝试,最终肯定操作成功)。
可见cas 其二的关键因子:跟近目标值,将其他线程的同步操作进行更新,然后操作。
cas 本质上也有锁,因为某一cpu或者线程正在操作值,恰恰另外的cpu也要进行操作,但是需要先获取目标值那么此时是不能获取目标值的,因为,cas对应的保护地址在操作中,其他cpu一旦又操作,地址将被锁住,或者缓存将被锁住。cas有对应的地址被记录而加锁保护,这种锁基于硬件的。
cas是硬件指令,c层代码可以调用,java层无法直接调用。
使用java 模拟cas操作:
public class CASCount implements Runnable {
private SimilatedCAS counter = new SimilatedCAS();
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(this.increment());
}
}
public int increment() {
int oldValue = counter.getValue();
int newValue = oldValue + 1;
while (!counter.compareAndSwap(oldValue, newValue)) { //如果CAS失败,就去拿新值继续执行CAS
oldValue = counter.getValue();
newValue = oldValue + 1;
}
return newValue;
}
public static void main(String[] args) {
Runnable run = new CASCount();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
}
class SimilatedCAS {
private int value;
public int getValue() {
return value;
}
// 这里只能用synchronized了,毕竟无法调用操作系统的CAS
public synchronized boolean compareAndSwap(int expectedValue, int newValue) {
if (value == expectedValue) {
value = newValue;
return true;
}
return false;
}
}