服装网站建设前景分析,建筑师网站有哪些,做企业的网站都要准备什么,中国手工加工网免费供货CAS介绍
CAS 称 自旋锁#xff0c;无锁#xff0c; 比较并换#xff0c;不用加锁也能保证原子性 CAS 的全称 为 Compare-And-Swap 它是一条CPU并发原语它的功能是判断内存某个位置的值是 否为预期值#xff0c;如果是则更改为新的值#xff0c;这个过程是原子 C…CAS介绍
CAS 称 自旋锁无锁 比较并换不用加锁也能保证原子性 CAS 的全称 为 Compare-And-Swap 它是一条CPU并发原语它的功能是判断内存某个位置的值是 否为预期值如果是则更改为新的值这个过程是原子 CAS原理 CAS操作由三个参数组成内存地址V、期望值A和新值B。CAS操作的基本流程如下 读取内存地址V中的当前值C。 如果C等于期望值A则将新值B写入内存地址V中。 如果C不等于期望值A则不做任何处理 CAS实现 CAS并发原语体现在JAVA语言中就sum.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法JVM会帮我们实现出CAS编指令。这是一种完全依赖于硬件的功能通过它实现了原子操作。再次强调由于CAS是一种系统原语原语属于操作系统用范畴是由若干条指令组成的用于完成某个功能的一个过程并且原语的执行必须是连续的在执行过程中不允许被中断也是说CAS是一条CPU的原子指令不会造成所谓的数据不一致问题。 Unsafe类 Unsafe 是CAS的核心类由于java方法无法直接访问底层系统需要通过本地native方法来访问Unsafe 相当于一个后门 基于该类可能直接操作特定内存的数据Unsafe 类存在于sum.misc 包中,其内部操作可以像C的指针一样直接操作内存因为java 中CAS操作的执行依赖于Unsafe类的方法。 注意Unsafe 类中的所有方法都是 native修饰的也就是说Unsafe 类中的方法都直接调用操作系统底层资源执行相应任务。
Unsafe 类部分代码 atomicInteger.getAndIncrement()的原理: 在Java中最底层是CompareAndSwap 无限自旋比较和交换。
public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); }
//自旋锁比较值是否相等不等不进行更新 public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 var4)); return var5; } CAS示例 public static void main(String[] args) { AtomicInteger countnew AtomicInteger(5); System.out.print(count.compareAndSet(5,10)\t countcount.get()); System.out.print(\ncount.compareAndSet(5,10)\t countcount.get()); }
结果 true count10 false count10 Process finished with exit code 0
CAS缺点
1 CPU开销过大
在并发量比较高的情况下如果许多线程反复尝试更新某一个变量却又一直更新不成功循环往复会给CPU带来很到的压力。
2 不能保证代码块的原子性只能保证一个共享变量的原子操作
CAS机制所保证的知识一个变量的原子性操作而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新就不得不使用synchronized了。
3 ABA问题 1线程A从主内存中拿了一份值 , 假如是10 , 它在自己的工作空间中打算进行修改了 (还没修改) 2这时线程B抢占了线程A , 它从主内存中将10取出来了, 它给修改成了22 , 放回主内存中了 , 但是呢 ,它感觉修改的不满意 , 又去主内存把那个22又取出来了 , 又给改成了10 , 然后走了 3这时线程A 去进行比较并交换 , 发现工作内存值和主内存值(期望值)是一样的都是10 , 就成功修改了, 但是 ! 注意 ! 线程A并不知道这个值中途被其他线程修改了 ! ! !