Skip to content

Commit

Permalink
feat: add case instruction reordering causes non-final field variab…
Browse files Browse the repository at this point in the history
…le read error (#64)
  • Loading branch information
WeiXiao-Hyy authored and oldratlee committed May 31, 2024
1 parent 042b533 commit f599bfe
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ Examples of concurrency problems you encountered in development are welcome to p
- [Demo description](#demo-description-7)
- [Problem statement](#problem-statement-7)
- [Quickly run](#quickly-run-7)
- [🍺 Instruction reordering causes non-final field variable read error](#-instruction-reordering-causes-non-final-field-variable-read-error)
- [Demo description](#demo-description-8)
- [Problem statement](#problem-statement-8)
- [Quickly run](#quickly-run-8)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand Down Expand Up @@ -233,3 +237,23 @@ this is a livelock.
```bash
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.ReentrantLockLivelockDemo
```

## 🍺 Instruction reordering causes non-final field variable read error

Demo class [`FinalInitialDemo`](src/main/java/fucking/concurrency/demo/FinalInitialDemo.java).

### Demo description

The writer thread calls the constructor of the class, and the reader thread obtains the member variables of the non-final domain of the class.

### Problem statement

When calling the constructor, instruction reordering may occur, placing non-final domain variables outside the constructor,
causing the writer and reader threads to obtain the default initial values of the variables.(Instruction ordering does not necessarily occur
and requires specific hardware and JVM environments).

### Quickly run

```bash
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.FinalInitialDemo
```
23 changes: 23 additions & 0 deletions docs/zh-CN/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
- [Demo说明](#demo%E8%AF%B4%E6%98%8E-6)
- [问题说明](#%E9%97%AE%E9%A2%98%E8%AF%B4%E6%98%8E-6)
- [快速运行](#%E5%BF%AB%E9%80%9F%E8%BF%90%E8%A1%8C-6)
- [🍺 指令重排序导致非final域变量读取错误](#-指令重排序导致非final域变量读取错误)
- [Demo说明](#demo%E8%AF%B4%E6%98%8E-7)
- [问题说明](#%E9%97%AE%E9%A2%98%E8%AF%B4%E6%98%8E-7)
- [快速运行](#%E5%BF%AB%E9%80%9F%E8%BF%90%E8%A1%8C-7)
- [一些并发的问题讨论和资料](#%E4%B8%80%E4%BA%9B%E5%B9%B6%E5%8F%91%E7%9A%84%E9%97%AE%E9%A2%98%E8%AE%A8%E8%AE%BA%E5%92%8C%E8%B5%84%E6%96%99)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
Expand Down Expand Up @@ -209,6 +213,25 @@ Demo类[`SymmetricLockDeadlockDemo`](../../src/main/java/fucking/concurrency/dem
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SymmetricLockDeadlockDemo
```

## 🍺 指令重排序导致非final域变量读取错误

Demo类[`FinalInitialDemo`](../../src/main/java/fucking/concurrency/demo/FinalInitialDemo.java)

### Demo说明

writer线程调用类的构造函数,reader线程获取类的非final的成员变量。

### 问题说明

调用构造函数时,可能会发生指令重新排序,将非final域变量放置在构造函数之外,导致writer和reader线程获取变量的默认初始值(指令顺序不一定发生,
并且需要特定的硬件和 JVM 环境)。

### 快速运行

```bash
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.FinalInitialDemo
```

## 一些并发的问题讨论和资料

- [ibm developerworks - 多核系统上的`Java`并发缺陷模式(`bug patterns`](http://www.ibm.com/developerworks/cn/java/j-concurrencybugpatterns/)
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/fucking/concurrency/demo/FinalInitialDemo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package fucking.concurrency.demo;


/**
* @author hyy (hjlbupt at 163 dot com)
*/
public class FinalInitialDemo {

private int a;
private boolean flag;
private FinalInitialDemo demo;

public FinalInitialDemo() {
a = 1;
flag = true;
}

public void writer() {
demo = new FinalInitialDemo();
}

public void reader() {
if (flag) {
int i = a * a;
if (i == 0) {
// On my dev machine, the variable initial always success.
// To solve this problem, add final to the `a` field and `flag` field.
System.out.println("Fuck! instruction reordering occurred.");
}
}
}

@SuppressWarnings("InfiniteLoopStatement")
public static void main(String[] args) throws Exception {
while (true) {
FinalInitialDemo demo = new FinalInitialDemo();
Thread threadA = new Thread(demo::writer);
Thread threadB = new Thread(demo::reader);

threadA.start();
threadB.start();

threadA.join();
threadB.join();
}
}
}

0 comments on commit f599bfe

Please sign in to comment.