Synchronized
JDK 1.6对synchronized进行了大量优化,使其不那么重了。如为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁。
Java中的每一个对象都可以作为锁,有以下三种形式:
(1):对于普通方法,锁是当前实例对象
(2):对于静态同步方法,锁是当前类的Class对象
(3):对于同步代码块,锁是synchronized括号里的对象
当一个线程试图访问同步代码块时,它必须先得到锁,退出或抛出异常时必须释放锁。那么锁存放在哪里呢?锁里面会存储什么信息呢?
JVM基于进入和退出Monitor对象来实现方法同步和代码块同步,代码块同步是通过monitorenter和monitorexit指令实现的。
monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法的结束处和异常处,JVM要求每个monitorenter必须有对应的monitorexit与之配对。
每个对象都有一个monitor与之关联,是每个对象与生俱来的隐藏字段,线程获取锁时,会根据锁对象头中的monitor状态进行加锁判断,如果monitor为0,就可以加锁持有锁,并将monitor置为1,如果当前线程已经持有了monitor,那么monitor继续加1(可重入),线程执行完毕释放锁则将monitor减1,直至monitor为0,则锁释放成功;如果monitor为1,表示锁已经被其他线程持有,则线程将处于BLOCKED阻塞状态。
总结:
Synchronized是JVM来实现的,JVM底层是通过监视锁来实现synchronized同步的。监视锁即monitor,是每个对象与生俱来的一个隐藏字段。通过在代码编译时,在同步代码块的前插入monitorenter指令和在代码块结束处和异常处插入monitorexit指令,分别对锁对象头中的monitor字段+1和-1实现加锁和释放锁的。
如果在进入同步代码块获取锁时,锁对象头中的monitor字段的值为0,那么则可以获取锁,并将monitor字段置为1,执行结束退出同步代码块时将monitor置为0释放锁。若当前线程已经持有了当前对象锁,则再次获取锁时,monitor继续加1,释放锁时monitor减1,直至monitor为0时,锁释放成功。
如果在获取锁时,锁对象的monitor为1,则表示锁已经被其他线程持有,则当前线程将出于阻塞状态。
END.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类