sychronized如何实现的?锁升级的过程?

sychronized的实现

   synchronized实现同步的基础具体表现为以下三种形式:

对于普通的方法来说,锁的是当前实例;

对于静态同步方法来说,锁的是当前类的Class对象

对于同步方法来说,锁的是synchronized括号里配置的对象。

实现原理:

  synchronized

代码块是由一对monitorenter  monitorexit指令实现,synchronized是通过对象内部的叫做监听器(monitor)实现的,线程通过monitotenter指令尝试获取minitor的所有权,当monitor被占用的时候,就会处于锁定状态。

获取monitor的所有权的过程如下:

  1. 如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者,代表持有锁;
  2. 如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1;
  3. 如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权;

锁升级

   在JVM底层实现锁的过程中,有三种类型的锁:偏向锁、轻量级锁、重量级锁。

所谓锁的升级、降级,就是JVM优化synchroniaed运行的机制,当JVM检测到不同的竞争状况时,会自动切换到适合的锁实现,这种切换就是锁的升级、降级。

偏向锁

       偏向锁是为了在单线程(没有出现多个线程并发)执行情况下,尽量减少不必要的轻量级锁带来的消耗,即提高性能。因为轻量级锁的加锁与释放锁,也需要多次执行CAS指令。而偏向锁只需要在切换线程设置ThreadID的时候,执行一次CAS原子指令。所以,偏向锁的作用是在只有一个线程执行同步块时,进一步提高性能。

        当没有线程并发出现时,默认会使用偏斜锁。JVM会利用CAS操作,在对象头上的Mark Word部分设置线程ID,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁。这样做的假设是基于在很多应用场景中,大部分对象生命周期中最多会被一个线程锁定,使用偏斜锁可以降低无竞争开销。

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

轻量级锁

       根据轻量级锁的实现,虽然轻量级锁不支持“并发”,遇到“并发”就要升级为重量级锁。但是轻量级锁可以支持多个线程以串行的方式访问同一个加锁对象。但是每次执行,都会小号重复加锁与解锁的性能开销。

轻量级锁的加锁过程

  1. 在代码进入同步块的时候,如果对象锁状态为无锁状态(lock标志位“01”,biased_lock标志位“0”),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(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 Wordlock标志位设置为“00”,即表示此对象处于轻量级锁定状态。
  5. 如果这个更新操作失败了,虚拟机首先会检查对象的Mark Word是否已经指向当前线程的栈帧。如果是,就说明当前线程已经拥有了这个对象的锁,那就可以直接进入同步块继续执行。否则说明多个线程竞争该对象的锁,轻量级锁就要升级为重量级锁,lock标志位的状态值变为“10”,Mark Word中存储的就是指向重量级锁(互斥量)的指针,后面等待锁的线程也要进入阻塞状态。 当前线程便尝试使用自旋来获取锁,自旋就是为了不让线程阻塞,而采用循环去获取锁的过程。

轻量级锁的解锁过程

  1. 通过CAS指令,尝试把线程中复制的Displaced Mark Word对象替换当前的Mark Word
  2. 如果替换成功,整个同步过程就完成了。
  3. 如果替换失败,说明有其他线程尝试过获取该锁,该锁已升级为重量级锁,那就要在释放锁的同时,通知其它线程重新参与锁的竞争。

重量级锁

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值