锁的底层实现
JDK早期的锁都是重量级的锁,都需要找操作系统去申请锁,效率低
后来做个改进 锁升级
锁升级的概念
synchronized (Object)
- 首先Object的对象头Markword上面记录这个线程的id ,某两位来标记着是什么类型的锁,对象头还记录着当前线程申请了这把锁(在线程来的时候,先不进行给他上锁,只是记录线程的id值)偏向锁
- 下次再来申请这把锁的时候,如果还是这个线程就不去考虑加锁了。【偏向于这个线程效率提高】
- 如果下次来的线程不是原来的是新的线程,下次来的线程id与记录的线程id不相等,这种情况下就进行锁升级 从偏向锁 ---> > > 自旋锁 (自旋锁默认是旋转10次)
- 最开始的线程占这锁,另外一个线程在自旋,当自自旋了10次之后还是这把锁,就升级为重量级锁,从操作系统哪里来申请资源。(这时候这个线程就成为等待状态不占CPU了)
什么情况下使用自旋锁比较好?
自旋锁有个特点,它占CPU但是它不访问操作系统,它是在用户态去解决问题,不经过内核态。因此它在加锁解锁上效率要比内核态高。重量级锁OS不占CPU进入到等待队列的线程,什么CPU开始运行分配时间片。
执行时间长的用系统锁 (synchronized),执行时间特别短且线程数量不多时,使用自旋锁