在 JDK 1.6 中对锁的实现引入了大量的优化。后端
减小锁操做的开销。安全
在看下面的内容之间,但愿你们对 Mark Word 有个大致的理解。Java 中一个对象在堆中的内存结构是这样的:微信
Mark Word 是这样的:数据结构
自旋锁的思想:
让一个线程在请求一个共享数据的锁时执行忙循环(自旋)一段时间,若是在这段时间内能得到锁,就能够避免进入阻塞状态。架构
自旋锁的缺点:
须要进行忙循环操做占用 CPU 时间,它只适用于共享数据的锁定状态很短的场景。性能
若锁被其余线程长时间占用,会带来许多性能上的开销。因此自旋的次数再也不固定。由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。优化
若是共享数据的锁定状态持续时间较短,切换线程不值得(会有上下文切换),能够利用自旋锁尝试必定的次数。操作系统
JIT 编译时,会去除不可能存在竞争的锁。经过 JIT 的逃逸分析来消除一些没有在当前同步块之外被其余线程共享的数据的锁的保护,经过逃逸分析在 TLAB 来分配对象,这样就不存在共享数据带来的线程安全问题。线程
减小没必要要的紧连在一块儿的 lock,unlock 操做,将多个连续的锁扩展成一个范围更大的锁。3d
为了在无线程竞争的状况下避免在锁获取过程当中执行没必要要的 CAS 原子指令,由于 CAS 原子指令虽然相对于重量级锁来讲开销比较小但仍是存在很是可观的本地延迟(由于 CAS 的底层是利用 LOCK 指令 + cmpxchg 汇编指令来保证原子性的,LOCK 指令会锁总线,其余 CPU 的内存操做将会被阻塞,由于 CPU 架构若是是 CMU 的话,控制信号、数据信号等是经过共享总线传到内存控制器中)。减小同一线程获取锁的代价,省去了大量有关锁申请的操做。
若是一个线程得到了锁, 那么锁就进入偏向模式,此时 Mark Word 的结构也变为偏向锁结构,当该线程再次请求锁时,无需再作任何同步操做,即获取锁的过程只须要检查 Mark Word 的锁标记位为偏向锁以及当前线程 Id 等于 Mark Word 的 ThreadId 便可,这样就省去了大量有关锁申请的操做。
这种锁实现的背后基于这样一种假设,即在真实的状况下咱们程序中的大部分同步代码通常都处于无锁竞争状态(即单线程执行环境),在无锁竞争的状况下彻底能够避免调用操做系统层面的重量级互斥锁(重量级锁的底层就是这样实现的),只须要依靠一条 CAS 原子指令就能够完成锁的获取及释放。当存在锁竞争的状况下,执行 CAS 指令失败的线程将调用操做系统互斥锁进入到阻塞状态,当锁被释放的时候被唤醒。
主要分为 3 步:
一、在线程进入同步块的时候,若是同步对象状态为无锁状态(锁标志为 01),虚拟机首先将在当前线程的栈帧中创建一个名为锁记录的空间,用来存储锁对象目前的 Mark Word 的拷贝。拷贝成功后,虚拟机将使用 CAS 操做尝试将对象的 Mark Word 更新为指向 Lock Record 的指针,并将 Lock Record 里的 owner 指针指向锁对象的 Mark Word。若是更新成功,则执行 2,不然执行 3。
二、若是这个更新动做成功了,那么这个线程就拥有了该对象的锁,而且锁对象的 Mark Word 中的锁标志位设置为 "00",即表示此对象处于轻量级锁定状态,这时候虚拟机线程栈与堆中锁对象的对象头的状态如图所示。
三、若是这个更新操做失败了,虚拟机首先会检查锁对象的 Mark Word 是否指向当前线程的栈帧,若是是就说明当前线程已经拥有了这个对象的锁,那就能够直接进入同步块继续执行。不然说明多个线程竞争锁,轻量级锁就要膨胀为重要量级锁,锁标志的状态值变为 "10",Mark Word 中存储的就是指向重量级锁的指针,后面等待锁的线程也要进入阻塞状态。而当前线程便尝试使用自旋来获取锁。自旋失败后膨胀为重量级锁,被阻塞。
由于虚拟机线程栈帧中的 Displaced Mark Word 是最初的无锁状态时的数据结构,因此用它来替换对象头中的 Mark Word 就能够释放锁。若是锁已经膨胀为重量级,此时是不能够被替换的,因此替换失败,唤醒被挂起的线程。
其实就是对象头中的 Mark Word 数据结构改变的过程。
只须要判断 Mark Word 中的一些值是否正确就行。
只有一个线程访问同步块时,使用偏向锁。
须要执行 CAS 操做自旋来获取锁。
若是执行同步块的时间比较少,那么多个线程之间执行使用轻量级锁交替执行。
会发生上下文切换,CPU 状态从用户态转换为内核态执行操做系统提供的互斥锁,因此系统开销比较大,响应时间也比较缓慢。
若是执行同步块的时间比较长,那么多个线程之间刚开始使用轻量级锁,后面膨胀为重量级锁。(由于执行同步块的时间长,线程 CAS 自旋得到轻量级锁失败后就会锁膨胀)
参考书籍:《深刻理解 Java 虚拟机》
搜索微信公众号:Java知其因此然,可免费领取某课、Java 后端面经等资源,还有统一环境(教你怎么配置一套开发环境)视频领取。