synchronized总结:怎么保证可见性、有序性、原子性
通过前面的篇章我们知道 synchronized 底层实际上通过JVM来实现的,同一时间只能有一个线程去执行synchronized 中的代码块。
一、原子性
原子性:既然同一时间只有一个线程去运行里面的代码,那么这个操作就是不能被其它线程打断的,所以这里天然就具有原子性了。
二、可见性
我们继续来说synchronized是怎么保证可见性的?
synchronized也是通过内存屏障保证可见性的。之前我们讲volatile的时候说过。
- Load屏障保证volatile变量每次读取数据的时候都强制从主内存读取;
- Store屏障每次volatile修改之后强制将数据刷新回主内存。
synchronized关键字也是通过内存屏障来保证可见性的。我们都知道sychronized底层是通过monitorenter的指令来进行加锁的、通过monitorexit指令来释放锁的。
但是很多人都不知道的一点是,
monitorenter指令其实还具有Load屏障的作用。也就是通过monitorenter指令之后,synchronized内部的共享变量,每次读取数据的时候被强制从主内存读取最新的数据。
同样的道理monitorexit指令也具有Store屏障的作用,也就是让synchronized代码块内的共享变量,如果数据有变更的,强制刷新会主内存。
这样通过这种方式,数据修改之后立即刷新回主内存,其他线程进入synchronized代码块后,使用共享变量的时候强制读取主内存的数据,上一个线程对共享变量的变更操作,它就能立即看到了。
synchronized底层竟然也是通过内存屏障来保证可见性的。
内存屏障保证有序性
synchronizd是怎么保证有序性的,之前volatile通过内存屏障来保证有序性的,没错,synchronized也是通过内存屏障来保证有序性的。
之前我们讲过,四条禁止指令重排序的内存屏障,不记得话,要记得看一下之前的篇章哦,这4条禁止重排序的内存屏障分别为:
- StoreStore屏障:禁止StoreStore屏障的前后Store写操作重排
- LoadLoad屏障:禁止LoadLoad屏障的前后Load读操作进行重排
- LoadStore屏障:禁止LoadStore屏障的前面Load读操作跟LoadStore屏障后面的Store写操作重排
- StoreLoad屏障:禁止LoadStore屏障前面的Store写操作跟后面的Load/Store 读写操作重排
同样的道理啊,也是通过monitorenter、monitorexit指令嵌入上面的内存屏障;monitorenter、monitorexit这两条指令其实就相当于复合指令,既具有加锁、释放锁的功能,同时也具有内存屏障的功能。
再画个图给你看一下,是怎么禁止重排序的:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2013-05-11 selenium RC 环境配置【转】
2013-05-11 ES之七:elasticsearch之Index Aliases