Java 将一个线程中的变量设置为另一个线程中的变量
为什么在另一个线程调用的Java 将一个线程中的变量设置为另一个线程中的变量,java,multithreading,Java,Multithreading,为什么在另一个线程调用的f()方法中,池没有设置为5 public class Main { private static int pool = 5; public static void main(String... arg) { Th t = new Th(); Thread thread = new Thread(t); thread.st
f()
方法中,池
没有设置为5
public class Main {
private static int pool = 5;
public static void main(String... arg) {
Th t = new Th();
Thread thread = new Thread(t);
thread.start();
while (true) {
if (pool >= 0)
System.out.println(pool--);
}
}
static void f() {
pool = 5;
System.out.println("main.Main.f:pool=" + pool);
}
}
class Th implements Runnable {
@Override
public void run() {
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Main.f();
}
}
}
输出:
5
4
3
2
1
0
main.Main.f:pool=5
main.Main.f:pool=5
main.Main.f:pool=5
main.Main.f:pool=5
我可以将
pool
声明为volatile
来修复它,但我不明白为什么它可以工作8(该行为有意义:您的main()
中没有sleep()
,因此它可以快速连续执行减量五次。然后在1000毫秒之后,以及f()之后的每秒钟调用
将池设置为5。一个线程写入的值不会总是被另一个线程读取。需要有一个“内存屏障”来保证可见性,将字段声明为volatile是获得该保证的一种方法
粗略地说,如果需要,您必须请求可见性,否则运行时可以将其作为优化跳过。例如,它可能使用寄存器来存储主线程的
pool
值,而不是更新堆中某个对象中的字段。您的代码并不表示其他线程应该能够告诉差异,因此允许运行时执行优化。可能重复@shmosel,而不是重复。这个问题与波动性无关。请参阅下面javadba的回答。问题是关于线程之间的值可见性。这都是关于波动性(或同步)@Nikem:在我看来,这个问题是关于未指明的行为。代码中有许多问题,以及解释您所看到的内容的各种因素。从阅读开始(链接到维基百科,谷歌会给您更多).Choice quote:这方面的主要警告是,似乎串行语义不会阻止不同线程拥有不同的数据视图。本质上,不要求一个线程看到另一个线程所做的更改,除非通过各种方式强制执行某些同步。每秒钟后,当池设置回5时,wh主线程不是很快又开始倒计时了吗?这就是问题的重点。@erickson啊,你是对的-因此,volatile
@erickson使用的原因将按照线程访问AtomicInteger方法的顺序对池进行更改。这将允许在任何同时进行的操作中一次只进行一次写入礼仪问题。