gpt4 book ai didi

java - 没有状态的对象在发布时是否始终可见?

转载 作者:行者123 更新时间:2023-11-30 07:49:59 25 4
gpt4 key购买 nike

假设我有课

public class Foo {
public void printHi() {
System.out.print("Hi");
}
}

在一些客户端代码中我做了类似的事情

public static void main() {
Foo foo = new Foo();
(new Thread(() -> {foo.printHi();})).start();
}

并取消调用 Thread Start 的 happens-before 保证。那么 Foo 引用是否可能对使用它的线程不可见,或者更糟的是,属于该类的方法不可见,但 Foo 引用是可见的。我不确定方法是如何存储在像字段这样的对象中的,但这假设它只是内存中属于该对象的东西,所以它可能有可见性问题,但我不确定。有人也可以向我解释那部分吗?

我问这个是因为 Foo 是不可变的,在 JCIP 书中 Goetz 说

“另一方面,即使不使用同步来发布对象引用,也可以安全地访问不可变对象(immutable对象)。为了保证初始化安全,必须满足所有不变性要求:不可修改的状态,所有字段都是最终的,并且是正确的构造”(Goetz,3.5.2)

但是,它没有任何 final 字段,所以它算作所有字段都是 final 吗?因为没有字段 = 所有字段?

最佳答案

有不同的方法可以得到相同的答案。

  1. 您的对象是不可变的,因为它没有可以修改的状态。

  2. 它的所有字段都是final , 因为没有字段不是 final .

  3. 没有可能的竞争条件,因为在访问时没有可以修改的数据。

  4. 即使有一些非finalFoo 中声明的字段, 调用 printHi() ,它不读取对象的状态,不存在潜在的数据竞争。请注意,这仅适用于 Foo 的确切实例, 由 new Foo(…) 制作表达式,因为子类可以覆盖 printHi()访问共享可变状态。

    需要强调的是,竞争条件是关于共享可变数据的,不一定是对象。所以如果printHi()访问共享 static不同类的变量,它可能会产生数据竞争,即使 Foo实例是不可变的和/或正确发布的。代码调用 foo.printHi()在另一个线程中是安全的,如果 printHi()不访问共享可变状态(或仅使用适当的保护)。

作为Elliott Frisch mentioned , lambda 表达式的行为就像一个不可变对象(immutable对象),因此即使没有 Thread.start()happens-before 关系,代码也是安全的或 Foo 的不变性(假设此后未修改 Foo 实例)。

关于java - 没有状态的对象在发布时是否始终可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48055504/

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