CAS简介
- CAS指令需要三个操作数,分别是内存地址(在Java内存模型中可以简单理解为主内存中变量的内存地址)、旧值(在Java内存模型中,可以理解工作内存中缓存的主内存的变量的值)和新值。
- CAS操作执行时,当且仅当主内存对应的值等于旧值(缓存)时,处理器用新值去更新旧值,否则它就不执行更新。但是无论是否更新了主内存中的值,都会返回旧值,上述的处理过程是一个原子操作。
知识点补充: 缓存的概念
- cpu处理数据中,频繁使用的内存会缓存 在处理器L1、L2、L3高速缓存里,那么数据的操作都会在处理器内部的缓存中进行。
- 目前处理器中可以使用"缓存锁定"的方式来处理数据的不一致,缓存锁定是指内存区域数据被缓存在处理器的告诉缓存中,并且在操作期间被锁定,那么它执行的锁操作会写到内存。
缓存锁与CAS的关系:
intel提供了很多Lock前缀的指令
java中主要涉及到缓存锁的操作是CAS操作,CAS操作正是使用了不同处理器下提供的缓存锁的指令。
CAS操作
在上图中,分别有两条线程A与B,其中线程A优先与线程B执行a++操作,,线程A工作内存缓存a的值为10,主内存中的a的值也为10,这个时候如果进行CAS操作,会与主内存中的a的值进行对比,如果相等会将执行a++操作后的值也就是11同步到主内存中,这个时候主内存中的值为11。当线程A执行完后,线程B接着执行,可是线程B中工作内存中缓存的a的值为8,根据缓存一致性原则。会重新去主内存读取a的值(11),此时线程B中工作内存中缓存的a的值为11,接着执行a++运算后a的值为12,此时将a的值12同步到主内存中。
补充缓存一致性:在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理通过嗅探在总线上传播的数据来检查自己的缓存的值是不是过期了,当处理器发现自己缓存的数据对应的内存地址被修改,就会将当前处理器缓存的数据处理为无效,当处理器对这个数据进行修改的操作的时候,会重新从系统内存中把数据读到处理器缓存中。
CAS出现的问题
1.ABA问题
- 因为CAS需要在操作值的时候,检查值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。
- ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加1,那么A→B→A就会变成1A→2B→3A。