首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何重现代码规范中提到的多线程错误?(TSM03-J.不要发布部分初始化的对象)

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

Stack Overflow用户
提问于 2019-12-20 02:38:06
回答 1查看 38关注 0票数 0

我正在使用谷歌翻译阅读"SEI CERT Oracle编码标准的Java“。

其中一个建议是TSM03-J.不要发布部分初始化的对象,它给出了将导致“发布部分初始化对象”的代码。

我想重现文章中提到的错误,但失败了。谁能给我举个例子吗?

不要与下面的场景混淆,尽管它也可以得到部分初始化的对象。TSM01 01-J.在对象构造过程中不要让此引用转义。

代码语言:javascript
复制
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;
  }
  // ...
}

然后在那一页上有解释

如果一个线程在执行initialize()方法之前使用getHelper()方法访问助手,那么该线程将观察到一个未初始化的助手字段。稍后,如果一个线程调用initialize(),另一个调用getHelper(),则第二个线程可以观察到以下情况之一:

  • 助手引用为null。
  • 一个完全初始化的Helper对象,其n字段设置为42
  • 带有未初始化n的部分初始化Helper对象,其中包含默认值0

为了测试目的,我在"Helper“中添加了以下代码

代码语言:javascript
复制
    public int getN() {
        return n;
    }

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

代码语言:javascript
复制
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;
                }
            }
        }
    }
}

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

EN

回答 1

Stack Overflow用户

发布于 2019-12-20 07:34:16

从同一页,

特别是,JMM允许编译器为新Helper对象分配内存,并在初始化新helper对象之前将对该内存的引用分配给Helper字段。换句话说,编译器可以重新排序对helper实例字段的写和初始化Helper对象(即that .n= n)的写,这样前者就会先发生。--这可以公开一个竞赛窗口,在此期间,其他线程可以观察到一个部分初始化的Helper对象实例。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59419247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档