java多线程之内存可见性

可见性:一个线程对共享变量值的修改,能够及时的被其他线程看到

要实现可见性必须保证两点要求:1 线程修改后的共享变量能够及时从工作内存刷新到主内存中  2 其他线程能够及时把共享变量的最新值从主内存中更新到自己工作内存中

共享变量:如果一个变量在多个线程的工作内存中都存在内存副本,那么这个变量就是这几个线程的共享变量

Java内存模型(JMM):Java内存模型(Java Memory Model)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量储存到内存和从内存中读取变量这样的底层细节     tz:这里的变量应该共享变量,如果不是共享变量就不会牵扯到数据的征用,所以也不用定义这些细节,帅帅

1.所有的变量都存储在主内存中

2.每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(主内存中该变量的一份拷贝)

JMM中有这么两条规定:1 线程对共享变量的所有操作只能在自己的工作内存中进行,不能直接从主内存中读写         2 不同线程之间不能直接访问其他线程中工作内存的变量,线程之间的共享变量值传递需要通过主内存来完成

Java语言层面支持可见性 实现方式有:1 synchronized  2 volatile

synchronized能够实现: 原子性(同步)           可见性

JMM关于synchronized的两条规定

1 线程解锁前,必须把共享变量的最新值刷新到主内存中

2 线程加锁时, 将清空工作内存中共享变量的值,从而使共享变量值需要从主内存中重新读取最新的值(注意:加锁与解锁需要是同一把锁

线程解锁前对共享变量的修改在下次加锁时对其他线程可见

synchronized实现可见性线程执行互斥代码的过程:1 获得互斥锁 2 清空工作内存 3 从主内存拷贝变量的最新副本到工作内存 4执行代码  5将更改后的共享变量刷新到主内存 6释放互斥锁

 


重排序:代码书写的顺序与实际执行的顺序不同,指令重排序是编译器或处理器为了提高程序性能而做的优化1 编译器优化的重排序(编译器优化)

2 指令级并行重排序(处理器优化)

3 内存系统的重排序(处理器优化)

as-if-serial :无论如何重排序,程序执行的结果应该与代码顺序执行的结果一致(Java编译器,运行时和处理器都会保证Java在单线程下遵循as-if-serial语义

int num1 = 1;

int num2 = 2;

int sum = num1 + num2;

单线程:第1,2可以重排,第3不行

重排序不会给单线程带来内存可见性问题,多线程由程序交错执行时,重排序可能会造成内存可见性问题

 

可见性分析导致共享变量在线程间不可见的原因:

1 线程的交叉执行

2 重排序结合线程交叉执行

3 共享变量更新后的值没有在工作内存与主内存间及时更新

synchronized解决方案:

1 原子性

2 原子性

3 可见性

 

volatile实现可见性

volatile关键字:能够保证volatitle变量的可见性   不能保证volatile变量复合操作的原子性

volatile如何实现内存可见性:深入来说,通过加入内存屏障和禁止重排序优化来实现的。

对volatile变量执行写操作时,会在写操作后加入一条store屏障指令

对volatile变量执行读操作时,会在读操作前加入一条load屏障指令

volatilr适用场合

要在多线程中安全的使用volatile变量,必须同时满足:

1 对变量的写入操作不依赖当前值

不满足:number++, count = count * 5

满足:boolean变量 ,记录温度变化的变量等

2 该变量没有包含在具有其他变量的不变式中

不满足: 不变式:flag < num

 

synchronized(下全用s表示) 和volatile(下全用v表示)比较

v不需要加锁,比s更轻量级,不会阻塞线程;

从内存可见性角度,v读相当于加锁,v写相当于解锁;

s既能保证可见性又能保证原子性,而v只能保证可见性,无法保证原子性;

 

posted on   胡子就不刮  阅读(147)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示