【多线程面试题十四】、说一说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来实现,被阻塞的线程会被挂起、等待重新调度,会导致"用户态和内核态"两个态之间来回切换,对性能有较大影响。

相关推荐
lee_curry5 小时前
第四章 jvm中的垃圾回收器
java·jvm·垃圾收集器
九转成圣6 小时前
Java 性能优化实战:如何将海量扁平数据高效转化为类目字典树?
java·开发语言·json
wxy不爱写代码6 小时前
C++多线程
面试·职场和发展
SmartRadio6 小时前
ESP32-S3 双模式切换实现:兼顾手机_路由器连接与WiFi长距离通信
开发语言·网络·智能手机·esp32·长距离wifi
laowangpython6 小时前
Rust 入门:GitHub 热门内存安全编程语言
开发语言·其他·rust·github
我叫汪枫6 小时前
在后台管理系统中,如何递归和选择保留的思路来过滤菜单
开发语言·javascript·node.js·ecmascript
_.Switch6 小时前
东方财富股票数据JS逆向:secids字段和AES加密实战
开发语言·前端·javascript·网络·爬虫·python·ecmascript
软件技术NINI6 小时前
webkit简介及工作流程
开发语言·前端·javascript·udp·ecmascript·webkit·yarn
Brendan_0016 小时前
JavaScript的Stomp.over
开发语言·javascript·ecmascript
念2346 小时前
f5 shape分析
开发语言·javascript·ecmascript