gpt4 book ai didi

java - 为什么这种竞争条件的输出有些一致?

转载 作者:行者123 更新时间:2023-12-03 17:32:15 25 4
gpt4 key购买 nike

当我运行以下代码时,最终输出始终为正,如果我切换“x++”和“x--”的顺序,则最终输出始终为负。这个竞争条件的哪些部分被跳过是否有某种顺序?非常感谢任何帮助理解!

public class DataRace {

private static class MyThreadCode implements Runnable {

private static int x = 0; // NOTE THAT X IS STATIC!!!

@Override
public void run() {
for (int i = 0; i < 10000000; i++) {
x++;
x--;
}
System.out.println(x + " " + Thread.currentThread().getName());
}
}

public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new MyThreadCode());
t.start();
}
}
}

最佳答案

我们这里有两个问题:

  • 因为 x++x--不是原子的(请参阅 Why is i++ not atomic? ),您会遇到竞争条件。
    线程 1 将加载值 x (0).然后 CPU 可以切换到线程 2,它也加载当前的 x (0).现在都在本地增加值,稍后,他们将设置 x .这意味着我们失去了一个增量。
  • 因为 x未标记 volatile我们也没有使用 synchronized关键字,您不能保证线程真的看到 x 的实际值.可能是该值已被另一个线程更新,但由于 Java 可见性保证,您无法保证其他线程看到什么(更新值或某些过时的“缓存”值)。也可能是其他Thread还没有写更新x值返回到内存(仅到 L1/L2 缓存)。

  • 我玩了一下代码,如果我减少 for循环到 1000迭代,我得到相同代码的负值和正值。如果我们有很多迭代,这可能暗示 JVM 会优化代码。如果我们只有 1000 次迭代,我猜这还不算多,JVM 可能会决定按照编写的代码运行代码。
    我怀疑这两个问题对结果都有一定的影响。例如,如果您加载 x ,处理器可能会将该值加载到 L1 缓存中,然后如果您执行第二个操作,它可能会直接从 L1 缓存而不是主内存加载该值。这可能意味着,第二次操作不会/更少导致“丢失更新”。
    但要真正找出发生这种情况的原因,我认为您需要深入研究 Java 规范,甚至 CPU 是如何处理这种情况的。

    关于java - 为什么这种竞争条件的输出有些一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67094426/

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