1.Synchronized锁的三种形式:
Synchronized修饰普通同步方法,锁的是调用当前方法的实例对象。
Synchronized修饰静态同步方法,锁的是当前类的class对象。
Synchnonized修饰同步代码块,锁的是Synchronized后面括号里配置的对象。
2.Synchronized在JVM里面怎么实现?
Synchronized锁是基于进入和退出monitor对象来实现方法和代码块同步的。通过monitorentry和monitorexit这两个指令来实现的。在同步开始位置插入monitorentry指令,在同步结束的位置或者异常出现的位置插入monitorexit指令。任何对象都有一个monitor阙值,当这个对象的monitor被持有后,它将处于锁定状态。
3.Synchronized锁对象是存在哪里的哪?
存在锁对象的对象头中,称为MarkWord。
4.锁升级
锁的4中状态:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态。
为什么要引入偏向锁?
大多数时候是不存在锁的竞争的,常常是一个线程多次获得同一个锁,为了减少每次竞争锁的代价,引入偏向锁。
偏向锁的升级?
当线程1访问代码块并获取锁对象时,会在java对象头和栈帧中记录偏向的锁的threadID。因为偏向锁不会主动释放,所以当线程1在此想获取锁的时候,返现threadID一致,则无需使用CAS来加锁,解锁。
如果不一致,线程2需要竞争锁,偏向锁不会主动释放里面还是存储线程1的threadID。如果线程1 没有存活,那么锁对象被重置为无锁状态,其他线程竞争并将其设置为偏向锁。
如果线程1 还存活,那么查看线程1是否需要持有锁,如果需要,升级为轻量级锁。如果不需要设置为无锁状态,重新偏向。
偏向锁默认开启。
为什么要引入轻量级锁?
轻量级锁考虑的是竞争锁对象的线程不多,而且线程持有锁的时间也不长的情景,为了避免阻塞线程让CPU从用户态转到内核态和代价,干脆不阻塞线程,直接让它自旋等待锁释放。
轻量级锁的升级?
线程1获取轻量级锁时会先把锁对象的对象头复制到自己的锁记录空间,然后使用CAS替换对象头的内容。
如果线程1复制对象头的同时,线程2 也准备获取锁,但是线程2在CAS的时候失败,自旋,等待线程1释放锁。
如果自旋到了次数线程1还没有释放锁,或者线程1在执行,线程2在自旋等待,这时3有来竞争,这个轻量级锁会膨胀为重量级锁,重量级锁把所有拥有锁的线程都阻塞,防止CPU空转。
几种锁的优缺点?