Java内存模型与final域:重排序规则解析
150 浏览量
更新于2024-09-01
收藏 169KB PDF 举报
"深入理解Java内存模型,重点讨论了final关键字在内存模型中的特殊规则,包括对final域的写入与引用赋值的不可重排序以及读取final域的限制。"
Java内存模型(JMM)是Java多线程编程中的一个重要概念,它规定了如何处理线程间的共享数据和通信。在Java中,final关键字用于声明不可变的变量,对于final域,JMM提供了额外的保证,以确保其特殊的行为。
首先,我们要明确两个关键的重排序规则:
1. 构造函数内的final域写入与将构造对象的引用赋值给引用变量之间不允许重排序。这意味着一旦对象构造完成,final域的值就被确定下来,其他线程无法看到这个对象的不完整状态,即final域未初始化的值。
2. 初次读取包含final域的对象引用与初次读取该final域本身之间不允许重排序。这保证了读线程在能够访问对象引用后,就能看到final域的正确初始化值。
以下是一个示例代码`FinalExample`,用于解释这两个规则:
```java
public class FinalExample {
int i; // 普通变量
final int j; // final变量
static FinalExample obj;
public FinalExample() { // 构造函数
i = 1; // 写普通域
j = 2; // 写final域
}
public static void writer() { // 写线程A执行
obj = new FinalExample();
}
public static void reader() { // 读线程B执行
FinalExample object = obj; // 读对象引用
int a = object.i; // 读普通域
int b = object.j; // 读final域
}
}
```
在这个例子中,线程A执行`writer()`方法创建并初始化`FinalExample`对象,而线程B执行`reader()`方法读取对象的成员。由于final域的重排序规则,线程B在获取到`obj`引用后,读取`j`的值时,可以确保`j`已经被正确初始化为2,即使`i`可能还没有被初始化。
为了实现这些规则,JVM会在final域写入后插入一个StoreStore屏障,防止处理器将final域的写操作重排序到构造函数之外。同时,JMM也阻止编译器进行这种重排序。这样,当线程B读取到`FinalExample`对象的引用时,它会看到一个final域已经初始化的对象,保证了数据一致性。
总结来说,Java内存模型对final域的特殊处理确保了线程安全性和可见性,使得final变量在多线程环境中能够作为不可变对象的基石,为并发编程提供了一种可靠的机制。理解并正确运用这些规则对于编写高效且正确的并发程序至关重要。
点击了解资源详情
点击了解资源详情
点击了解资源详情
2019-05-06 上传
2018-05-20 上传
2019-04-19 上传
2019-04-02 上传
2018-10-17 上传
2021-09-30 上传
weixin_38750003
- 粉丝: 7
- 资源: 927
最新资源
- C语言数组操作:高度检查器编程实践
- 基于Swift开发的嘉定单车LBS iOS应用项目解析
- 钗头凤声乐表演的二度创作分析报告
- 分布式数据库特训营全套教程资料
- JavaScript开发者Robert Bindar的博客平台
- MATLAB投影寻踪代码教程及文件解压缩指南
- HTML5拖放实现的RPSLS游戏教程
- HT://Dig引擎接口,Ampoliros开源模块应用
- 全面探测服务器性能与PHP环境的iprober PHP探针v0.024
- 新版提醒应用v2:基于MongoDB的数据存储
- 《我的世界》东方大陆1.12.2材质包深度体验
- Hypercore Promisifier: JavaScript中的回调转换为Promise包装器
- 探索开源项目Artifice:Slyme脚本与技巧游戏
- Matlab机器人学习代码解析与笔记分享
- 查尔默斯大学计算物理作业HP2解析
- GitHub问题管理新工具:GIRA-crx插件介绍