Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/java/basic/4、final关键字特性.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ final修饰的函数会被编译器优化,优化的结果是减少了函数调

在上图中,写普通域的操作被编译器重排序到了构造函数之外,读线程 B 错误的读取了普通变量 i 初始化之前的值。而写 final 域的操作,被写 final 域的重排序规则“限定”在了构造函数之内,读线程 B 正确的读取了 final 变量初始化之后的值。

写 final 域的重排序规则可以确保:在对象引用为任意线程可见之前,对象的 final 域已经被正确初始化过了,而普通域不具有这个保障。以上图为例,在读线程 B“看到”对象引用 obj 时,很可能 obj 对象还没有构造完成(对普通域 i 的写操作被重排序到构造函数外,此时初始值 2 还没有写入普通域 i)。
写 final 域的重排序规则可以确保:在对象引用为任意线程可见之前,对象的 final 域已经被正确初始化过了,而普通域不具有这个保障。以上图为例,在读线程 B“看到”对象引用 obj 时,很可能 obj 对象还没有构造完成(对普通域 i 的写操作被重排序到构造函数外,此时初始值 1 还没有写入普通域 i)。

### 读 final 域的重排序规则

Expand All @@ -495,8 +495,8 @@ final修饰的函数会被编译器优化,优化的结果是减少了函数调
reader() 方法包含三个操作:

1. 初次读引用变量 obj;
2. 初次读引用变量 obj 指向对象的普通域 j
3. 初次读引用变量 obj 指向对象的 final 域 i
2. 初次读引用变量 obj 指向对象的普通域 i
3. 初次读引用变量 obj 指向对象的 final 域 j

现在我们假设写线程 A 没有发生任何重排序,同时程序在不遵守间接依赖的处理器上执行,下面是一种可能的执行时序:

Expand Down