gpt4 book ai didi

java - 由类的方法延迟分配的非 volatile 变量是否可以不被另一个线程读取?

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

考虑以下代码:

import java.util.concurrent.Callable;

final public class DelayedSet {
String Val = "Uninitialized";

public Callable<String> Makegetter(String val) {
this.Val = val;
return new Callable<String>() {
public String call() {
return DelayedSet.this.Val;
}
};
}
}

class Main {
public static void main(String[] args) {
DelayedSet x = new DelayedSet();
Callable<String> Foogetter = x.Makegetter("Initialized");
// Version 1
try {
System.out.println(Foogetter.call());
}
catch (Exception e) {
}
}
}

运行Main后,会打印“Initialized”。

现在考虑变体A,其中Foogetter被传递到一个新线程。那么 Foogetter 是否也会返回“Initialized”,或者由于缓存条件过时,Foogetter 是否有可能返回“Uninitialized”?

还要考虑变体 B,其中我们有三个线程:T1T2T3T1 通过 futures,向 T2 提交一个 Callable,其中 T2 创建 DelayedSet ,调用 Makegetter,并通过 future 返回到 T1,并返回 "Foogetter"(在引号中,因为它在技术上是匿名的)。然后,T1 获取此结果("Foogetter"),并提交另一个可调用对象,这次提交给 T3,其中 T3 调用 “Foogetter”。对于这两种变体,是否保证返回“Initialized”,或者是否可以返回“Uninitialized”?

用伪代码总结:

T1:
futureT2 = executorService.submit(new Callable {
...
call() {
// Runs in T2
Foo = new DelayedSet;
return Foo.Makegetter("Initialized");
} ...
futureT3 = executorService.submit(futureT2.get());
print(futureT3.get());

来自此question ,我的印象是需要依赖同步事件来搭载,例如 volatile 或同步块(synchronized block)。然而,我试图确定特殊情况不需要 volatile (即使通过捎带),但由于线程创建和加入的语义发生之前,不会产生任何过时的缓存条件。

任何人都可以澄清有关线程的内存模型是什么,以便回答这个问题吗?

最佳答案

对于变体A,我将假设类似

new Thread(() -> {
try {
System.out.println(Foogetter.call());
} catch (Exception e) {
}
}).start();

在本例中,the JLS has us covered

A call to start() on a thread happens-before any actions in the started thread.

this.Val = val;

发生在 Makegetter 调用中,该调用发生在调用 Thread#start() 之前,然后发生在调用 call 之前启动的线程。返回的值必须始终为“Initialized”

变体B中,首先要注意的是Future的内存一致性效应

Actions taken by the asynchronous computation happen-before actions following the corresponding Future.get() in another thread.

futureT2.get()T1 中返回时,T2 中的 call 调用已经发生(-before) 并且 MakeGetter 的调用已经设置了 DelayedSet.Val 的值。此更改对获取 CallableT1 和返回此更新值的 T3 以及再次对 T1 可见它使用 futureT3.get() 检索它。

关于java - 由类的方法延迟分配的非 volatile 变量是否可以不被另一个线程读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29001781/

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