java对象头(32位来看)64bit前32是mark word,后32位是Klass word,后指向的是对象的类型如int类型,student类型等指向了对象从属的class对象
mark word中最后位置为001是正常状态,101是偏向锁,00轻量级锁,10重量级锁
Monitor(锁)也叫监视器或者管程 是操作系统层面提供的
每个java对象可以关联一个Monitor对象,当使用synchronized给对象加锁(重量级)时,对象头中的mark word就设置为指向Monitor对象的指针
轻量级锁使用场景:一个对象有多个线程访问,但没有发生竞争,可以使用轻量级锁来优化
轻量级锁解锁时:取值为null的锁记录,表示锁重入,直接去掉表示减一,不为null时,使用cas将mark word的值恢复给对象头,如果失败表示发生了锁膨胀变成了重量级锁,需要进入重量级锁解锁流程
锁膨胀:
自旋优化:重量级锁在竞争时,另一个线程访问同步代码块,获取不到Monitor时不会立即进入阻塞状态,会进行几次自旋重试,如果成功则加锁,不成功就进入阻塞(成功可以避免阻塞,减少一次上下文切换)java6之后自旋锁是自适应的,如果成功次数多会多自旋几次,反之一样,自旋也会占用CPU时间,单核没必要自旋,多核自旋才有用。
偏向锁:第一次使用CAS将线程ID设置到对象头的mark word,之后再发现这个线程id是自己的表示没有竞争,不需要再重新CAS;当一个对象调用了hashcode方法后会撤销偏向状态,因为hashcode占用31个位置,位置不够;当有其他线程也使用偏向锁对象时(不是竞争),会升级为轻量级锁;当撤销偏向锁阈值超过20次会对新的线程发起重新偏向;如果撤销超过40次,就将偏向锁撤销,改为不可偏向。
锁消除:JIT会优化掉没有必要的锁