问题:什么是CAS,CAS的原理是什么?
什么是CAS的ABA问题?怎么解决?
synchronized地锁升级过程是怎么样的?
ReentrantLock底层的加锁和解锁是怎么实现的?
为什么说ReentrantLock是默认非公平锁?
什么是公平锁什么是非公平锁什么是可重入锁?
什么是CAS,CAS的原理是什么
cas叫自旋锁是线程锁的一种状态,cas的实现是这样的过程,当多个线程在争抢一个锁的时候,某一个线程获取到了这个锁,其他线程就在自旋等待,隔一会就来看一下这个锁是否轮到我了。一个经典的比喻在马士兵课上马老师说过,我是厕所所长的比喻。下面是Unsafe的源码,看并发这块的源码必读Unsafe源码,我是从SynchronousQueue类点进去看的
然后我看到了这样一段代码
UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
compareAndSwapObject:比较并且交换当前对象。
貌似JDK1.8之前这块的代码叫做compareAndSet。
意思就是比较这个值和我期望的值是不是一样的,不是的话那我在去自旋等待。如果是哪我就去修改当前值变成我当前线程期望的那个值然后这个锁就是当前线程的。锁修改值的时候是原子性的。cas的底层hospot源码的最后一条指令叫做 lock cmpxchg hospot是c++写的,c++指定操作的是系统的CPU。属于CPU原语级别的指令。
但是cas会有一个非常著名的ABA问题,这个问题是这样的:假如现在一个线程 “张三” 在自旋等待他的线程期望值为2,当前这个锁的值为3有一个线程在使用这个锁,“张三”来了看到这个锁不是我的期望值,那么拿到当前这个锁上的值变成自己的期望值继续等待,当他做这个操作的时候,来了两个线程 A,B。这个时候这个锁被上一个人用完,A抢占了这个锁,然后一通操作结束让出这个锁了,锁上的值为4。这个时候“张三”还在做自己的操作,B线程也做了一通操做走了。把当前锁上的值改为了3。当“张三”线程再来的时候发现和我期望值一样,好现在这个锁归我了。这个就是ABA问题,这里有个很牛的比喻叫做,“你知道你前女朋友和你分手后隔了一年复合她经历了多少个男人?”
这个ABA问题最好的解决办法是加版本号。每次修改记录一下版本号。
synchronized地锁升级过程是怎么样的
synchronized的锁升级过程其实就是面试中常问的四种锁状态。
- 无锁
- 偏向锁
- 轻量级锁
- 重量级锁
锁是怎么升级的:一开始在创建的new对象就是无锁的状态,当第一个线程过来的时候这个时候只有这一个线程,当前锁的状态为偏向锁。当好几个线程过来发生锁竞争了这个时候升级为轻量级锁(CAS自旋锁)。当线程越来越多,都在自旋这个时候非常消耗CPU资源,这个时候升级为重量级锁,所有的等待线程进入线程队列等待cpu的调度。
ReentrantLock底层的加锁和解锁是怎么实现的?
ReentrantLock底层是AQS然后aqs里面有一个共享的int类型的值state这个值被voaltile修饰,ReentrantLock每次加锁state这个值就+1每次解锁这个值就-1
为什么说ReentrantLock是默认非公平锁
因为AQS底层有一个双向链表队列,新来的线程可以直接去抢锁。当没抢到的时候就进队列。
什么是公平锁什么是非公平锁什么是可重入锁
公平锁:线程先检查队列里面有没有,如果有就先等着排队,没有的话就直接执行
非公平锁:直接执行不检查队列
可重入锁:可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。