gpt4 book ai didi

java - 意外的线程行为。能见度

转载 作者:行者123 更新时间:2023-11-29 06:52:44 24 4
gpt4 key购买 nike

我有以下代码:

public static boolean turn = true;

public static void main(String[] args) {
Runnable r1 = new Runnable() {
public void run() {
while (true) {
while (turn) {
System.out.print("a");
turn = false;
}
}
}
};
Runnable r2 = new Runnable() {
public void run() {
while (true) {
while (!turn) {
System.out.print("b");
turn = true;
}
}
}
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}

在类里面,我们学习了使用非同步代码时可能出现的“可见性”问题。据我所知,为了节省时间,编译器将决定抓取 turn 到 CPU 中的缓存进行循环,这意味着线程不会知道是否 turn 值在 RAM 中被更改,因为他没有检查它。

据我了解,我希望代码像这样运行:

T1 将看到 turn 为 true -> 进入循环并打印 -> 将 turn 变为 false -> 卡住

T2 会认为转弯没有改变 -> 会卡住

我希望如果 T1 在 T2 之前开始:只会打印 'a' 并且两个线程将在无限循环中运行而不打印任何其他内容

但是,当我运行代码时,有时我会在两个线程都卡住之前收到一些“ababa...”。

我错过了什么?

编辑:

下面的代码符合我的预期:线程将在无限循环中运行:

public class Test extends Thread {
boolean keepRunning = true;

public void run() {
long count = 0;
while (keepRunning) {
count++;
}
System.out.println("Thread terminated." + count);
}

public static void main(String[] args) throws InterruptedException {
Test t = new Test();
t.start();
Thread.sleep(1000);
t.keepRunning = false;
System.out.println("keepRunning set to false.");
}

它们之间有什么不同?

最佳答案

When I run the code, sometimes I get a few "ababa...." before both threads will stuck.

我怀疑发生的事情是当代码被 JIT 编译时行为发生了变化。在 JIT 编译之前,写入是可见的,因为解释器正在执行直写。在 JIT 编译之后,缓存刷新或读取已被优化掉......因为内存模型允许这样做。

What am I missing ?

您缺少的是您希望未指定的行为 保持一致。它不一定是。毕竟,它是未指定的! (这是真的,即使我上面提出的解释是不正确的。)

关于java - 意外的线程行为。能见度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42176913/

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