gpt4 book ai didi

java - 如何重现代码规范中提到的多线程错误?(TSM03-J。不要发布部分初始化的对象)

转载 作者:行者123 更新时间:2023-12-01 19:15:51 24 4
gpt4 key购买 nike

我正在使用 Google 翻译阅读“SEI CERT Oracle Coding Standard for Java”。

建议之一是 TSM03-J. Do not publish partially initialized objects ,它给出了导致“发布部分初始化的对象”的代码

我想重现文章中提到的错误,但失败了。有人可以给我示例代码吗?

不要与以下场景混淆,尽管它也可以获得部分初始化的对象。 TSM01-J. Do not let the this reference escape during object construction

class Foo {
private Helper helper;

public Helper getHelper() {
return helper;
}

public void initialize() {
helper = new Helper(42);
}
}

public class Helper {
private int n;

public Helper(int n) {
this.n = n;
}
// ...
}

然后该页面上有说明

If a thread were to access helper using the getHelper() method before the initialize() method executed, the thread would observe an uninitialized helper field. Later, if one thread calls initialize() and another calls getHelper(), the second thread could observe one of the following:

  • The helper reference as null
  • A fully initialized Helper object with the n field set to 42
  • A partially initialized Helper object with an uninitialized n, which contains the default value 0

出于测试目的,我将以下代码添加到“Helper”

    public int getN() {
return n;
}

以下是测试代码,我以为测试代码会输出“发布部分初始化的对象”,但什么也没发生。

public class Program {
public static void main(String[] args) {
boolean getZero = false;
while (!getZero) {

Foo foo = new Foo();
new Thread(foo::initialize).start();

while (true) {
Helper helper;
if ((helper = foo.getHelper()) != null) {
if (helper.getN() == 0) {
getZero = true;
System.out.println("publish partially initialized objects");
}
break;
}
}
}
}
}

如何重现代码规范中提到的多线程错误?

最佳答案

在同一页面,

In particular, the JMM permits compilers to allocate memory for the new Helper object and to assign a reference to that memory to the helper field before initializing the new Helper object. In other words, the compiler can reorder the write to the helper instance field and the write that initializes the Helper object (that is, this.n = n) so that the former occurs first. This can expose a race window during which other threads can observe a partially initialized Helper object instance.

要在这里观察部分初始化的对象,您的代码需要在读取 foo.getHelper().getN() 时点击此竞争窗口。你可以运行它数百万次,但仍然不会发生这种情况。与大多数多线程相关的错误一样,它不容易复制。

关于java - 如何重现代码规范中提到的多线程错误?(TSM03-J。不要发布部分初始化的对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59419247/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com