Synchronized底层实现 + Synchronized锁优化_大白话

Synchronized同步,被修饰的方法块,同步方法,每次都只让一个线程去执行。那么那么,他底层是怎么实现的呢?

对于synchronized语句当Java源代码被javac编译成bytecode的时候,会在同步块的入口位置和退出位置分别插入monitorentermonitorexit字节码指令。而synchronized方法则会被翻译成普通的方法调用和返回指令如:invokevirtual、areturn指令,在VM字节码层面并没有任何特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized标志位置1,表示该方法是同步方法并使用调用该方法的对象或该方法所属的Class在JVM的内部对象表示Class做为锁对象。JVM中monitorenter和monitorexit字节码依赖于底层的操作系统的Mutex Lock来实现的。

 

//郑重的、简单的再次说明一下, 当我们synchronized锁住的是代码块的时候, 他会在代码块上下加上monitorentermonitorexit字节码指令,当程序执行到monitorenter 是,我们的锁会去获取对象头的monitor。当锁获取到了monitor,便会在锁计数器上+1,然后释放锁的时候,便会在锁计数器上 -1 。0表示当前没有锁。 

但是我们要是加载 方法上面我们就是在 添加一个 access_flags 标记位。来判断该方法是不是同步方法。然后就是执行相应的方法。

当我们进行线程切换的时候,需要操作系统进行从用户态切换成内核态。这是一个很消耗时间的操作。所以下面锁优化。

 

你这样说一下已经可以征服很多人了,但是也有面试官会恶心的问你。Synchroized锁优化。

因为操作系统的这个Mutex Lock操作是非常耗费时间的。他需要将线程从用户态切换到内核态,这个切换时非常耗时间的。

锁粗化:很好理解,如下

lock();   unlock();   lock();    unlock();   优化后:lock() ; unlock();

就是在连续的加锁释放锁情况下,当前线程需要被频繁的从用户态切换内核态。这很恐怖呀。直接就是用一次加锁释放锁。

锁消除:通过编译器的逃逸分析消除一些没有在当前同步块以外被其他线程共享的数据的锁保护,

轻量级锁:在没有无锁竞争的情况下,我们可以使用cas锁来对monitorenter和monitorexit中间的代码块进行加锁。(怎么检测是不是无所的情况下?, 我自己觉得哈,就是看当前锁对象的锁池里面有没有线程。)当存在锁竞争的情况下,cas指令及时执行失败,然后就会去调用系统的互斥锁(Mutex_lock)

偏向锁:无所的情况下,我们不去加锁,不使用cas加锁,cas有本地延迟的情况出现。

适应性自旋:当线程在获取轻量级锁的过程中执行CAS操作失败时,在进入与monitor相关联的操作系统重量级锁(mutex semaphore)前会进入忙等待(Spinning)然后再次尝试,当尝试一定的次数后如果仍然没有成功则调用与该monitor关联的semaphore(即互斥锁)进入到阻塞状态。(很清楚的一次,当我们获取轻量级锁的时候,操作cas失败,我们会去重试多次,当重试一定的次数之后,还是失败,就会进入互斥锁阶段。系统使用mutex_lock)

 

释放锁(monitorexit)的大概过程如下:

(1)首先检查该对象是否处于膨胀状态并且该线程是这个锁的拥有者,如果发现不对则抛出异常;

(2)检查Nest字段是否大于1,如果大于1则简单的将Nest减1并继续拥有锁,如果等于1,则进入到(3);

(3)检查rfThis是否大于0,设置Owner为NULL然后唤醒一个正在阻塞或等待的线程再一次试图获取锁,如果等于0则进入到(4)

(4)缩小(deflate)一个对象,通过将对象的LockWord置换回原来的HashCode值来解除和monitor record之间的关联来释放锁,同时将monitor record放回到线程是有的可用monitor record列表。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值