gpt4 book ai didi

Java谜题: busy wait threads stop working

转载 作者:行者123 更新时间:2023-12-01 23:52:06 26 4
gpt4 key购买 nike

这是某种 Java 谜题,我偶然发现但无法真正解释。也许有人可以?

以下程序在短时间内挂起。有时在 2 个输出之后,有时在 80 个输出之后,但几乎总是在正确终止之前。如果第一次没有发生,您可能需要运行几次。

public class Main {
public static void main(String[] args) {
final WorkerThread[] threads = new WorkerThread[]{ new WorkerThread("Ping!"), new WorkerThread("Pong!") };
threads[0].start();
threads[1].start();

Runnable work = new Runnable() {
private int counter = 0;
public void run() {
System.out.println(counter + " : " + Thread.currentThread().getName());
threads[counter++ % 2].setWork(this);
if (counter == 100) {
System.exit(1);
}
}
};

work.run();
}
}

class WorkerThread extends Thread {
private Runnable workToDo;

public WorkerThread(String name) {
super(name);
}

@Override
public void run() {
while (true){
if (workToDo != null) {
workToDo.run();
workToDo = null;
}
}
}

public void setWork(Runnable newWork) {
this.workToDo = newWork;
}
}

现在,很明显,繁忙的等待循环一般来说并不是一个好主意。但这不是为了改进,而是为了了解正在发生的事情。

因为当 WorkerThread.setWork()synchronized 或当 WorkerThread.workToDo 字段设置为 时,一切都会按预期工作 volatile 我怀疑内存有问题。

但到底为什么会发生这种情况呢?调试没有帮助,一旦开始单步执行,一切都会按预期运行。

如有解释,我们将不胜感激。

最佳答案

  1. 第一个问题是您从 main 线程设置 Runnable workToDo,然后在 2 个 fork 线程中读取它而不进行同步。每当您在多个线程中修改字段时,都应将其标记为 volatile 或某人同步

    private volatile Runnable workToDo;
  2. 此外,由于多个线程正在执行 counter++,因此也需要同步。为此,我推荐使用 AtomicInteger

    private AtomicInteger counter = new AtomicInteger(0);
    ...
    threads[counter.incrementAndGet() % 2].setWork(this);
  3. 但我认为真正的问题可能是竞争条件之一。两个线程都可以将 workToDo 设置为 Runnable,然后让它们都返回并将其设置回 null,以便它们将会永远旋转。我不知道如何解决这个问题。

    1. threads[0] has it's `workToDo` set to the runnable.  It calls `run()`.
    2. at the same time threads[1] also calls `run()`.
    3. threads[0] sets the `workToDo` on itself and threads[1] to be the runnable.
    4. at the same time threads[1] does the same thing.
    5. threads[0] returns from the `run()` method and sets `workToDo` to be `null`.
    6. threads[1] returns from the `run()` method and sets `workToDo` to be `null`.
    7. They spin forever...

而且,正如您提到的,旋转循环很疯狂,但我认为这是一个演示线程程序。

关于Java谜题: busy wait threads stop working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16179525/

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