synchronized实现原理

synchronized (this) {
     while (sharedState < 100000) {
         int former = sharedState++;
         int latter = sharedState;
         if (former != latter - 1) {
             System.out.printf("数据观察结果: former is %d,latter is %d", former, latter);
         }
     }
}

这样一段简单的源代码会被java编译成字节码文件,字节码文件由0和1的二进制数组成,这样的文件可读性较低,java为我们提供了一套助记符。所以上面的源文件就可以被javap反编译成下面的由助记符代替的字节码文件。

 

monitorenter和monitorexit指令实现了synchronized代码块中的内容。

monitor叫做监视器,线程通过执行monitorenter尝试获取monitor的所有权,当monitor被占用时就会处于锁定状态。

Owner:存放获取monitor所有权的线程。 

EntryList:存放被阻塞的线程。

WaitSet:存放处于等待状态的线程。


锁升级

在 Java 6 之前, synchronized 的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的 切换,所以同步操作是一个无差别的重量级操作,非常消耗系统资源。

在Java 6 之后,提供了三种不同的 Monitor 实现,也就是常说的三种不同的锁:偏斜锁( Biased Locking )、轻量级锁和重量级锁。

偏向锁:(只能是单线程)

偏向锁是在单线程(没有出现多个线程并发)情况下执行,当没有线程并发出现时,默认会使用偏斜锁。 JVM 会利用 CAS 操作(compare and swap),在对象头上的 Mark Word 部分设置线程 ID ,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁。使用偏斜锁可以降低无竞争开销。

轻量级锁:(线程串行执行)

轻量级锁可以支持多个线程以串行的方式访问同一个加锁对象。但是,每次执行,都消耗了重复的加锁与解锁的性能开销。

1,在代码进入同步块的时候,如果对象锁状态为无锁状态,虚拟机首先将在当前线程的栈帧中建立一个名为锁记录( Lock Record )的空间,用于存储锁对象目前的 Mark Word 的拷贝,官方命名为 Displaced Mark Word 。

2, 拷贝对象头中的 Mark Word 复制到锁记录( Lock Record )中。

3, 拷贝成功后,虚拟机将尝试将对象的 Mark Word 中的ptr_to_lock_record更新为指向 Lock Record 的指针,并将 Lock record 里的 owner 指针指向到对象的 Mark Word 。如果更新成功,则执行步骤4,否则执行步骤5。

4, 如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象 Mark Word 的lock标志位设置为“ 00 ”,即表示此对象处于轻量级锁定状态。

5, 如果这个更新操作失败了,虚拟机首先会检查对象的 Mark Word 是否已经指向当前线程的栈帧。如果是,就说明当前线程已经拥有了这个对象的锁,那就可以直接进入 同步块继续执行。否则说明多个线程竞争该对象的锁, 就要升级为 重量级锁,lock标志位的状态值变为“ 10 ”, Mark Word 中存储的就是指向重量级锁(互 斥量)的指针,后面等待锁的线程也要进入阻塞状态。 当前线程便尝试使用自旋来获 取锁,自旋就是为了不让线程阻塞,而采用循环去获取锁的过程。

重量级锁:(线程并法执行):

依赖于操作系统互斥锁( Mutex Lock )所实现的锁。操作系统的互斥锁实现线程之间的切换,需要从用户态 转换到核心态,切换成本非常高,状态之间的转换需要相对比较长的时间,这是早期 Synchronized 效率低的 原因。因此,这种依赖于操作系统互斥锁( Mutex Lock )所实现的锁,称之为“重量级锁”。


 如果有另外的线程试图锁定某个已经被偏斜过的对象, JVM 就需要撤销( revoke )偏斜锁,并切换到轻量级锁实现。轻量级锁依赖 CAS 操作 Mark Word 来试图获取锁,如果重试成功,代表之前的线程执行完毕,就使用普通的轻量级锁;否则, 进一步升级为重量级锁。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值