13.synchronized总结:怎么保证可见性、有序性、原子性?

简介: 13.synchronized总结:怎么保证可见性、有序性、原子性?

synchronized的原子性

通过前面的篇章我们知道 synchronized 底层实际上通过JVM来实现的,同一时间只能有一个线程去执行synchronized 中的代码块。

原子性:既然同一时间只有一个线程去运行里面的代码,那么这个操作就是不能被其它线程打断的,所以这里天然就具有原子性了。

image.png

synchronized通过内存屏障保证可见性

老王:小陈啊,之前我们讲volatile的时候说过,volatile的可见性是通过什么来保证的

小陈:这个我还记得啊,volatile是通过内存屏障来保证可见性的Load屏障保证volatile变量每次读取数据的时候都强制从主内存读取Store屏障每次volatile修改之后强制将数据刷新会主内存

小陈:老王啊,难道说synchronized关键字也是通过内存屏障来保证可见性的?

老王:哈哈,小陈你的猜想没错。

我们都知道sychronized底层是通过monitorenter的指令来进行加锁的、通过monitorexit指令来释放锁的

但是很多人都不知道的一点是,monitorenter指令其实还具有Load屏障的作用

也就是通过monitorenter指令之后,synchronized内部的共享变量每次读取数据的时候被强制从主内存读取最新的数据。

同样的道理monitorexit指令也具有Store屏障的作用,也就是让synchronized代码块内的共享变量,如果数据有变更的,强制刷新回主内存。

这样通过这种方式,数据修改之后立即刷新回主内存,其他线程进入synchronized代码块后,使用共享变量的时候强制读取主内存的数据,上一个线程对共享变量的变更操作,它就能立即看到了。

老王:画个图给你看一下,大概是这样子的:

image.png

小陈:原来是这样啊,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这两条指令其实就相当于复合指令,既具有加锁、释放锁的功能,同时也具有内存屏障的功能。

再画个图给你看一下,是怎么禁止重排序的:

image.png

小陈:老王啊,你真的是太太太厉害了......,小弟佩服得五体投地啊

小陈:少吹了,你按照我的并发文章目录的文章顺序学习下去,你也能达到这个地步,这可是当年我师父教给我的,我现在把它传给你了....

老王:小陈啊,今天的这篇是我们这边《练气篇》里的最后一篇了,讲完这个我们接下来就要进入《结丹篇》了,也就是意味着前面的篇章学完了之后,你底层的基础巩固得差不多了。

小陈:嘿嘿,经过前面两个阶段《筑基》、《练气》 的学习,我对底层的只是包括CPU缓存模型、JAVA内存模型、volatile底层原理、内存屏障、synchronized的底层原理、synchronized底层加锁过程、锁升级过程、Mark Word、monitor的锁原理等等都了解得比以前深入太多了,哈哈,这都多亏了老王啊

小陈:这让我对接下来要讨论的内容越发的期待起来了啊,哈哈......

老王:前面的只是还有不懂的,要记得回去再看下哦.

我们目前《筑基》、《练气》两篇目前就到这里了,你在修炼之路上基础也打得差不多了。所以你要准备一下,需要一支翡翠神竹、一枚金菩果,以此来进入下一个境界《结丹》。

小陈:好的,老王,我们下一篇见。

相关文章
|
6月前
|
安全 Java 编译器
【面试问题】说说原子性、可见性、有序性?
【1月更文挑战第27天】【面试问题】说说原子性、可见性、有序性?
|
4月前
|
安全 Java 开发者
探索Java内存模型:可见性、有序性和并发
在Java的并发编程领域中,内存模型扮演了至关重要的角色。本文旨在深入探讨Java内存模型的核心概念,包括可见性、有序性和它们对并发实践的影响。我们将通过具体示例和底层原理分析,揭示这些概念如何协同工作以确保跨线程操作的正确性,并指导开发者编写高效且线程安全的代码。
|
6月前
|
缓存 安全 Java
多线程的三大特性:原子性、可见性和有序性
多线程的三大特性:原子性、可见性和有序性
141 0
|
6月前
|
缓存 安全 Java
3.线程安全之可见性、有序性、原子性是什么?
3.线程安全之可见性、有序性、原子性是什么?
72 0
3.线程安全之可见性、有序性、原子性是什么?
|
6月前
|
缓存 安全 Java
5.volatile是什么?怎么保证可见性?
5.volatile是什么?怎么保证可见性?
72 0
5.volatile是什么?怎么保证可见性?
|
6月前
|
安全 Java
7.volatile怎么通过内存屏障保证可见性和有序性?
7.volatile怎么通过内存屏障保证可见性和有序性?
61 0
7.volatile怎么通过内存屏障保证可见性和有序性?
volatile 的作用是什么?能保证原子性吗?能保证有序性吗?
volatile 的作用是什么?能保证原子性吗?能保证有序性吗?
115 0
|
存储 缓存 安全
JUC之可见性和有序性
JUC之可见性和有序性
|
缓存 Java 编译器
并发编程(三)原子性&可见性&有序性
并发编程(三)原子性&可见性&有序性
121 0
|
缓存 Java
Java并发中的可见性和原子性
Java并发中的可见性和原子性
113 0
Java并发中的可见性和原子性