java提供两种实现锁的机制,像Syncronized这种,是通过JVM来实现。
而像AtocmicInteger,这些concurrent包中的一些类是通过CAS原语来保证。
CAS基于CPU硬件指令来完成的。
基本原理:一个旧值(每次更新操作语句前,从内存中取出的值),一个新值(操作的结果值),一个期望值(在调用cpu的CompareAndSet时的方法,会从内存中取出最新值)
这时比较旧值和期望值是否相同,相同就将新值写入到内存。
java通过调用JNI(C实现),来提供CAS操作的几个封装类,语句如下:
unsafe.compareAndSwapInt(this, valueOffset, expect, update);
类似:
if (this == expect) {
this = update
return true;
} else {
return false;
}
这里的this,指CPU一二级缓存,对应的变量存储地址
这里有个问题,如果保证this==expect和this=update语句的原子性?
单CPU时,不需要考虑这个问题。但存在多CPU怎么办?
注:CPU能够保证单字节的原子性。有些处理器能够保证8/16/32/64操作的原子性。
cpu提供两种机制来保证 :
1.锁住总线,即CPU1执行compareAndSet时,发出一个LOCK命令,锁住整个总线,这时其它CPU无法再进行内存操作,开销较大。
2.利用缓存锁定,只锁定内存变量对应的CPU一二级缓存地址。即控制,对于同一个内存变量,多个CPU在一二级缓存中对其回写操作,只有第一个生效。
这时之后的n个CPU会触发cache失效,需要从内存中取最新的变量值,这时需要通过总线来取。
过多的CPU cache失效,会导致总线流量过大。