java线程在创建之前访问外部对象

use*_*135 19 java multithreading anonymous inner-classes

是的,这是一个学术问题,我知道人们会抱怨我没有发布任何代码,但我真的很震惊这个问题,真的不知道从哪里开始.我真的很感激解释和一些代码示例.

如果对象构造函数启动一个执行匿名内部类对象的方法运行的新线程,则该新线程可能在完全构造并且其字段完全初始化之前可以访问其周围的外部对象.你会如何防止这种情况发生?

Raf*_*ele 20

这被称为"泄漏这个".这里有代码

public class Test {

  // this is guaranteed to be initialized after the constructor
  private final int val;

  public Test(int v) {
    new Thread(new Runnable() {
      @Override public void run() {
        System.out.println("Val is " + val);
      }
    }).start();
    this.val = v;
  }

}
Run Code Online (Sandbox Code Playgroud)

猜猜它会是什么(可能,因为它是一个线程)打印.我使用一个final字段来强调在完全初始化之前访问对象(必须在每个构造函数的最后一行之后明确赋值)

你怎么恢复

this当你在构造函数中时,你不想传递.这也意味着您不希望在同一个类(非静态,非私有)中调用非最终虚方法,而不使用内部类(匿名类是内部类),这些类与封闭内容密切相关实例,因此它们可以访问this.

  • 很好的答案,如果你回答你自己的问题"猜猜它会打印什么",我会赞成.(一个随机值或0?)另外我没有得到"你不想在同一个类中调用非最终虚拟方法(非静态,非私有)"的部分,":你能提供一个例子吗?那个? (2认同)

Tho*_*mas 10

首先考虑单线程情况:

无论何时通过创建对象new,都会调用其构造函数(希望)在返回对此对象的引用之前初始化新对象的字段.也就是说,从调用者的角度来看,这new几乎就像一个原子操作:

在打电话之前new,没有任何对象.返回后new,对象存在完全初始化.

一切都很好.


当多个线程发挥作用时,情况会略有变化.但我们必须仔细阅读你的引用:

......已经完全建成并且其领域已经完全初始化.

关键的一点是fully.你问题的主题是"创建之前",但这里的含义不是在创建对象之前,而是在对象创建和初始化之间.在多线程情况下,new由于这个原因(时间从左向右流动)不再被视为(伪)原子:

Thread1 --> create object --> initialize object --> return from `new`
                           ^
                           |
                           | (messing with the object)
Thread2 ------------------/
Run Code Online (Sandbox Code Playgroud)

那么Thread2如何搞乱对象呢?它需要对该对象的引用,但由于new只有在创建和初始化之后才返回该对象,这应该是不可能的,对吧?

好吧,不 - 有一种方法仍然可以 - 即如果在对象的构造函数内创建线程2 .然后情况会是这样的:

Thread1 --> create object --> create Thread2 --> initialize object --> return from `new`
                                      |       ^
                                      |       |
                                      |       | (messing with the object)
                                       \-----/
Run Code Online (Sandbox Code Playgroud)

由于Thread2是在创建对象之后创建的(但在它完全初始化之前),因此已经有一个对Thread2可以获取的对象的引用.一种方法是简单地,如果Thread2的构造函数显式地将对象的引用作为参数.另一种方法是通过对Thread2的run方法使用对象的非静态内部类.