gpt4 book ai didi

java - 测试 final 字段的初始化安全性

转载 作者:IT老高 更新时间:2023-10-28 21:13:01 26 4
gpt4 key购买 nike

我正在尝试简单地测试 JLS 所保证的最终字段的初始化安全性。这是为了我正在写的一篇论文。但是,根据我当前的代码,我无法让它“失败”。谁能告诉我我做错了什么,或者如果这只是我必须一遍又一遍地运行然后看到一些不幸的时机失败?

这是我的代码:

public class TestClass {

final int x;
int y;
static TestClass f;

public TestClass() {
x = 3;
y = 4;
}

static void writer() {
TestClass.f = new TestClass();
}

static void reader() {
if (TestClass.f != null) {
int i = TestClass.f.x; // guaranteed to see 3
int j = TestClass.f.y; // could see 0

System.out.println("i = " + i);
System.out.println("j = " + j);
}
}
}

我的线程这样调用它:

public class TestClient {

public static void main(String[] args) {

for (int i = 0; i < 10000; i++) {
Thread writer = new Thread(new Runnable() {
@Override
public void run() {
TestClass.writer();
}
});

writer.start();
}

for (int i = 0; i < 10000; i++) {
Thread reader = new Thread(new Runnable() {
@Override
public void run() {
TestClass.reader();
}
});

reader.start();
}
}
}

我已经运行过这个场景很多很多次了。我当前的循环产生了 10,000 个线程,但我已经完成了这 1000、100000 甚至一百万个线程。仍然没有失败。对于这两个值,我总是看到 3 和 4。我怎样才能让它失败?

最佳答案

我编写了规范。 TL;这个答案的 DR 版本是,仅仅因为它可能看到 y 为 0,并不意味着它保证看到 y 为 0。

在这种情况下,正如您所指出的,最终字段规范保证您将看到 x 为 3。将编写器线程视为具有 4 条指令:

r1 = <create a new TestClass instance>
r1.x = 3;
r1.y = 4;
f = r1;

您可能看不到 3 for x 的原因是编译器重新排序了这段代码:

r1 = <create a new TestClass instance>
f = r1;
r1.x = 3;
r1.y = 4;

在实践中通常实现对 final 字段的保证的方式是确保构造函数在任何后续程序操作发生之前完成。想象一下,有人在 r1.y = 4 和 f = r1 之间竖起了一道巨大的屏障。因此,在实践中,如果您有对象的任何最终字段,您很可能会获得所有这些字段的可见性。

现在,理论上,有人可以编写一个没有以这种方式实现的编译器。事实上,很多人经常谈论通过编写最恶意的编译器来测试代码。这在 C++ 人中尤为常见,他们的语言中有很多未定义的角落,可能会导致严重的错误。

关于java - 测试 final 字段的初始化安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5066866/

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