如 指令),不会造成所谓的数据不一致问题,提供的CAS方法( 三 )


如  指令),不会造成所谓的数据不一致问题,提供的CAS方法

文章插图
它最终是由操作系统的汇编指令完成的 。
3.4.4、总结
你只需要记住:CAS是靠硬件实现的从而在硬件层面提升效率,最底层还是交给硬件来保证原子性和可见性
实现方式是基于硬件平台的汇编指令,在intel的CPU中(X86机器上),使用的是汇编指令指令 。
核心思想就是:比较要更新变量的值V和预期值E(),相等才会将V的值设为新值N(swap)如果不相等自旋再来 。
4、原子引用 4.1、原子整型,可否有其它原子类型?
4.2、
package com.atguigu.juc.cas;import lombok.AllArgsConstructor;import lombok.Getter;import lombok.ToString;import java.util.concurrent.atomic.AtomicReference;/*** @auther zzyy* @create 2021-03-19 22:13*/public class AtomicReferenceDemo{public static void main(String[] args){User z3 = new User("z3",24);User li4 = new User("li4",26);AtomicReference atomicReferenceUser = new AtomicReference<>();atomicReferenceUser.set(z3);System.out.println(atomicReferenceUser.compareAndSet(z3,li4)+"\t"+atomicReferenceUser.get().toString());System.out.println(atomicReferenceUser.compareAndSet(z3,li4)+"\t"+atomicReferenceUser.get().toString());}}@Getter@ToString@AllArgsConstructorclass User{String userName;intage;}
5、自旋锁,借鉴CAS思想 5.1、是什么
自旋锁()
是指尝试获取锁的线程不会立即阻塞,而是 采用 循环的方式去尝试获取锁 ,
当线程发现锁被占用时,会不断循环判断锁的状态,直到获取 。这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗 CPU
源码里面查看下 .java
5.2、自己实现一个自旋锁
package com.atguigu.juc.cas;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicReference;/*** @auther zzyy* @create 2021-03-17 15:21* 题目:实现一个自旋锁* 自旋锁好处:循环比较获取没有类似wait的阻塞 。** 通过CAS操作完成自旋锁,A线程先进来调用myLock方法自己持有锁5秒钟,B随后进来后发现* 当前有线程持有锁,不是null,所以只能通过自旋等待,直到A释放锁后B随后抢到 。*/public class SpinLockDemo{AtomicReference atomicReference = new AtomicReference<>();public void MyLock(){System.out.println(Thread.currentThread().getName()+"\t"+"---come in");while(!atomicReference.compareAndSet(null,Thread.currentThread())){}System.out.println(Thread.currentThread().getName()+"\t"+"---持有锁成功");}public void MyUnLock(){atomicReference.compareAndSet(Thread.currentThread(),null);System.out.println(Thread.currentThread().getName()+"\t"+"---释放锁成功");}public static void main(String[] args){SpinLockDemo spinLockDemo = new SpinLockDemo();new Thread(() -> {spinLockDemo.MyLock();try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }spinLockDemo.MyUnLock();},"t1").start();new Thread(() -> {spinLockDemo.MyLock();spinLockDemo.MyUnLock();},"t2").start();}}
5.3、CAS缺点 5.3.1、循环时间长开销很大 。
我们可以看到方法执行时,有个do while
如果CAS失败,会一直进行尝试 。如果CAS长时间一直不成功,可能会给CPU带来很大的开销 。
5.3.2、引出来ABA问题???
ABA问题怎么产生的
CAS会导致“ABA问题” 。
CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并替换,那么在这个时间差类会导致数据的变化 。
比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且线程two进行了一些操作将值变成了B,
然后线程two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后线程one操作成功 。
尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的 。