gpt4 book ai didi

java - 无法使用 static var 在 java 线程中获得预期输出

转载 作者:行者123 更新时间:2023-11-30 02:50:32 26 4
gpt4 key购买 nike

嗨,我正在尝试运行下面的代码,但对输出感到困惑:

它有时也会给我输出如下:答:7中:8乙:7

这里,一旦静态值更改为 8,之后 B 线程将要运行并打印其值 7,这是怎么可能的!我的意思是 i 是静态变量,那么它只有一个副本。

public class ThreadStaticTest implements Runnable {

static int i = 5;

public static void main(String[] args) {
ThreadStaticTest obj = new ThreadStaticTest();
Thread t1 = new Thread(obj);
Thread t2 = new Thread(obj);
Thread t3 = new Thread(obj);

t1.setName("A");
t2.setName("B");
t3.setName("C");

t1.start();
t2.start();
t3.start();
}

@Override
public void run() {
i++;
System.out.println(Thread.currentThread().getName()+" : "+i);
}
}

最佳答案

想想i++作为三种不同的操作:

  1. 获取i (到了JVM栈上,JVM就是一个栈机)
  2. 增加堆栈顶部
  3. 将堆栈顶部存储回变量 i .

确实,OpenJDK 8 的 javac 编译 run()方法进入:

public void run();
Code:
0: getstatic #11 // Field i:I
3: iconst_1
4: iadd
5: putstatic #11 // Field i:I

此外,因为 i不是 volatile 的,允许 JVM 优化读取访问,也就是说,它可以重新使用堆栈上已有的值 println()称呼。所以println() call 通常会从当前线程的角度看到该值,而不是存储的值。当字节码被编译成可以访问多个寄存器的 native 代码时,事情只会变得“更糟”。

有一个getstatic println() 之前调用在字节代码中,但是——正如所指出的——它可能会被优化掉。无论如何,无法保证它会读取什么值。您甚至无法确定打印的值是同一线程之前看到的值。

现在,考虑以下操作顺序,假设 i = 6 .

  1. 线程 A:获取 i
  2. 线程 C:获取 i
  3. 线程 A:增量 i
  4. 主题 A:商店 i
  5. 线程 B:获取 i
  6. 线程 B:增量 i
  7. 主题 B:商店 i
  8. 线程 C:增量 i
  9. 线程 C:商店 i

我们得到什么?

  • A 获取 6和商店7 ,可能会打印 7 .
  • B 获取 7和商店8 ,可能会打印 8 .
  • C 获取 6和商店7 ,可能会打印 7 .

每次运行你应该得到不同的结果,因为没有什么可以保证这个执行顺序。

关于java - 无法使用 static var 在 java 线程中获得预期输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38804962/

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