java - JVM在使用synchronized时如何保证被引用对象中成员变量修改的可见性?
问题描述
我想知道JVM在使用同步时如何保证被引用对象中成员变量修改的可见性。
我知道 synchronized 和 volatile 将为变量修改提供可见性。
class Test{
public int a=0;
public void modify(){
a+=1;
}
}
//Example:
// Thread A:
volatile Test test=new Test();
synchronized(locker){
test.modify();
}
// then thread B:
synchronized(locker){
test.modify();
}
// Now, I think test.a==2 is true. Is it ok? How JVM implements it?
// I know the memory barrier, does it flush all cache to main storage?
线程 A 先在一个块中调用 modify sychronized
,然后将对象传递给线程 B(将引用写入volatile
变量。)。然后线程 B 再次调用 modify(在 中synchronized
)。
a==2 有什么保证吗?JVM是如何实现的?
解决方案
线程之间的可见性通过Memory Barriers/Fences强制执行。在synchronized
块的情况下,JVM 将在块执行完成后插入内存屏障。
JVM 使用 CPU 指令实现内存屏障,例如使用x86上的指令完成存储屏障sfence
和使用指令完成加载屏障。lfence
还有mfence
可能特定于 CPU 架构的其他指令。
推荐阅读
- python - 高波动数据优化与预测
- flutter - 无法使用 GetX 显示下拉菜单按钮值
- azure - Quarkus:MDC 未在 Azure Application Insights 中公开
- python - 在 Python 中生成密码的安全问题?
- .net - “IConfigurationSection”不包含“Get”的定义,也没有可访问的扩展
- notifications - 在 Microsoft Teams 聊天中添加自定义通知或消息
- python - pandas:如何将列表存储在 excel 的 sqlite 数据库中
- django - 如何在 Django 中接受和拒绝订单
- sql - 如何同时使用内连接和左外连接?
- angular - 私有标识符仅在面向 ECMAScript 2015 及更高版本(Angular 9)时可用