【每日阅读】2021年02月01日-synchronized是如何实现的

真诚的希望您能留言与我交流,这会对我有非常大的帮助!

Java在进入synchronized代码段时,如果看字节码,会发现虚拟机执行了monitorenter指令,退出synchronized代码段时会执行monitorexit指令。如果执行monitorenter时发现对象计数器是0,则直接获取锁,如果不是0就检查当前锁是否被当前线程获取,如果是,就将计数器加一;每次执行monitorexit时都将计数器减一。

然后文章继续谈到了锁在hotspot内的3种实现。

重量级锁

每次加锁时都依靠操作系统提供的机制(例如符合posix接口的操作系统是通过pthread的互斥锁mutex实现的)来阻塞住当前线程,然后等待被唤醒。这个操作是会耗费很多系统资源的,所以叫做重量级锁。

不过Java对这种重量级锁是有优化的,就是自旋,每次不进入阻塞状态,而是先循环空跑一会儿,如果这段时间获取到锁了,那么就省去了一个阻塞又被唤醒的过程。

轻量级锁

先不加锁,而是先利用CAS机制操作替换锁对象的标记字段。CAS成功则代表加锁成功,否则代表加锁失败,Java会将锁升级为重量级锁,并阻塞当前线程。

偏向锁

偏向锁幻想:从始至终只有一个线程请求锁。

如果一个锁支持偏向锁操作,则会先尝试通过CAS操作将当前线程地址标记在锁的标记字段中,这样后序获取偏向锁时,看一下线程地址就知道能不能获取这个锁了。

如果CAS操作失败,会升级为轻量级锁。

原创文章,作者:geekgao,如若转载,请注明出处:https://www.geekgao.cn/archives/2809

发表评论

邮箱地址不会被公开。 必填项已用*标注

GitHub
分享本页
返回顶部