【多线程面试题十四】、说一说synchronized的底层实现原理

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。

面试官:说一说synchronized的底层实现原理

参考答案:

一、synchronized作用在代码块时,它的底层是通过monitorenter、monitorexit指令来实现的。

  • monitorenter:

    每个对象都是一个监视器锁(monitor),当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

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

  • monitorexit:

    执行monitorexit的线程必须是objectref所对应的monitor持有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个monitor的所有权。

    monitorexit指令出现了两次,第1次为同步正常退出释放锁,第2次为发生异步退出释放锁。

二、方法的同步并没有通过 monitorenter 和 monitorexit 指令来完成,不过相对于普通方法,其常量池中多了 ACC_SYNCHRONIZED 标示符。JVM就是根据该标示符来实现方法的同步的:

当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。

三、总结

两种同步方式本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。两个指令的执行是JVM通过调用操作系统的互斥原语mutex来实现,被阻塞的线程会被挂起、等待重新调度,会导致"用户态和内核态"两个态之间来回切换,对性能有较大影响。

相关推荐
m0_74823595几秒前
SpringBoot:解决前后端请求跨域问题(详细教程)
java·spring boot·后端
LUCIAZZZ15 分钟前
简单说一下什么是RPC
java·网络·网络协议·计算机网络·spring cloud·rpc
嘵奇18 分钟前
最新版IDEA下载安装教程
java·intellij-idea
终极定律24 分钟前
qt:输入控件操作
开发语言·qt
JenKinJia39 分钟前
Windows10配置C++版本的Kafka,并进行发布和订阅测试
开发语言·c++
煤炭里de黑猫41 分钟前
Lua C API :lua_insert 函数详解
开发语言·lua
笨鸟笃行43 分钟前
爬虫第七篇数据爬取及解析
开发语言·爬虫·python
s_fox_44 分钟前
Nginx Embedded Variables 嵌入式变量解析(4)
java·网络·nginx
编程乐趣44 分钟前
一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略来了!
开发语言·c#
一个 00 后的码农1 小时前
25旅游管理研究生复试面试问题汇总 旅游管理专业知识问题很全! 旅游管理复试全流程攻略 旅游管理考研复试真题汇总
考研·面试·面试问题·考研复试·旅游管理·复试调剂·面试真题