Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将一个线程中的变量设置为另一个线程中的变量_Java_Multithreading - Fatal编程技术网

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方法的顺序对池进行更改。这将允许在任何同时进行的操作中一次只进行一次写入礼仪问题。