1.讲解CAS概念
CAS使用了乐观锁的概念,实现了原子操作那么什么是原子操作,其实可以理解为一个事务,下图表示
CAS内部执行原理:
传入旧值跟新值让compare去比较内存中已经存在的旧值,如果传入进来的旧值跟内存中的旧值一致那就把传入进来的新增修改,如果不相等则采用自旋的方式拿到内存中的旧值在再次进行比较,自旋可以可以理解为自旋锁机制含义
那这里小伙伴们肯定会产生疑问了这cas不是有3步独立的指令了吗,
指令1拿到:内存地址的值
指令2拿到:我传入进来的旧值
指令3拿到:我传入进来的新值
那多线程并法会不会导致我指令重排掉呢,这一点小伙伴们可以不必担心因为CPU处理器以及为我们提供了专门的CAS指令,可以保证指令顺序执行并将原子的更新值
CAS存在的问题:
ABA问题:线程A更新值时比较的旧值为3,由于并发速度太快了现在线程B在线程A更新值时又把数据更新为3,此时线程A更新成功。就比喻小明接满一杯水玩去了,小狗偷偷摸摸的过来把水喝了一半又把他接满了,此时小明回来了咦发现水还是满的小明就喝了
解决:可以采用AtomicMarkableReference,AtomicStampedReference进控制
开销问题:由于存在并发情况同时修改值,如果值被改过了,就会重新获取内存中的值进行比较,在此期间如果一直修改不成功,会导致做死的循环,会有性能损耗
解决:没必要解决总会成功的,不管他
只能保证一个共享变量的原子操作:每次更新操作我只能更新一个值,即一个CAS指令,如果有连个CAS指令那就时独立的了不能保证原子操作
解决:可以通过AtomicReference定义一个对象(对象里面包含多个更新的字段),即可解决这个问题
既然谈到了锁那就给小伙伴们讲几个java中常用的锁吧
锁:单线程下锁是没有意义的,就是没有锁,锁的话是多线程下的,锁其实说的更加简单一点就是一个事务,一个保证线程之间共享资源的一种安全机制
一个锁里面可以包含其他的锁,比如同步锁里面有(偏向锁,独占锁,重入锁等等)
锁粒度:就是锁的级别,锁住的资源越小发生死锁的几率也就越小,比喻我家,我的房间每次只允许一个人进入那就锁住我的房间就好了,没必要把我家锁了,一次只能进入一个人那比如爸回家了不可能让他在外面等着吧
锁开销:一个锁的占用内存跟所需执行完毕需要的时间,就是锁的性能开销
锁竞争:线程相互排斥对方,竞争一个锁资源,锁的粒度越小发生的竞争越就越小
---------------------------------------------------------------------------------------------
偏向锁:也可以称为单线程记录锁,比喻线程A拿到了锁然后操作完了准备退出了,但是不会释放锁资源,此时线程A又来请求锁,此时会判断锁的话是不是线程A的如果是直接用就好了,如果不是是线程B的那就会释放掉线程A的锁资源,让线程B拿到锁资源,那此时锁就是线程B的了,此时其他的线程要来请求锁也是跟线程B去拿线程A的锁资源操作是一样