Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 为什么关于线程的代码显示a=1和b=3?为什么要加一个“;易挥发;没有';不行?_Java_Multithreading_Thread Safety_Atomic_Volatile - Fatal编程技术网

Java 为什么关于线程的代码显示a=1和b=3?为什么要加一个“;易挥发;没有';不行?

Java 为什么关于线程的代码显示a=1和b=3?为什么要加一个“;易挥发;没有';不行?,java,multithreading,thread-safety,atomic,volatile,Java,Multithreading,Thread Safety,Atomic,Volatile,代码如下: public class ThreadCacheSample { int a = 1; int b = 2; public void change() { a = 3; b = a; } public void print() { if (a == 1 && b == 3) { // why this is happening?

代码如下:

public class ThreadCacheSample {
    int a = 1;
    int b = 2;

    public void change() {
        a = 3;
        b = a;
    }

    public void print() {
        if (a == 1 && b == 3) {
            // why this is happening?
            System.out.println("Thread[" + Thread.currentThread().getName() + "]Confused1 : a = 1, b = 3");
        } else if (a == 3 && b == 2) {
            // why this is happening, too?
            System.out.println("Thread[" + Thread.currentThread().getName() + "]Confused2 : a = 3, b = 2");
        } else {
            System.out.println("Thread[" + Thread.currentThread().getName() + "] b=" + b + ";a=" + a);
        }
    }

    public static void main(String[] args) {
        // create many many threads
        while (true) {
            // create test every time, to make sure a is 1 and b is 2 again
            final ThreadCacheSample test = new ThreadCacheSample();

            // one thread for changing
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    test.change();
                }
            }).start();

            // one thread for printing
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    test.print();
                }
            }).start();

        }
    }
}    
结果应该是a=1、b=2或a=3、b=3

我的问题是:

  • 为什么我会得到一些显示“a=1,b=3”或“a=3,b=2”的结果

  • 如果我在a和b中加上“volatile”,为什么不起作用? 我认为volatile会让每个线程只访问主内存,而不是自己的工作内存。因此,挥发性应该是一种解决方案。但现实告诉我,“不稳定”也不是解决办法

    public class ThreadCacheSample {
        volatile int a = 1;
        volatile int b = 2;
        ...
    }
    

  • p、 这不是一个关于如何修复代码的问题。这是关于为什么会出现奇怪的结果

    添加volatile会分别增加
    a
    b
    修改的可见性(以及在修改可见性之间添加排序依赖性)。然而,它并没有在它们的组合修改中添加任何种类的“原子性”。无论是否“易失性”,修改
    a
    和修改
    b
    (以及读取
    a
    和读取
    b
    )仍然是独立的操作

    您的两个“困惑”答案都是可能的:

    案例1:

  • init,a==1,b==2
  • 打印线程测试“a==1”
  • 更改螺纹组“a=3”
  • 更改螺纹组“a=b”(3)
  • 打印线程测试“b==3”
  • 混乱的1
  • 案例2:

  • init,a==1,b==2
  • 更改螺纹组“a=3”
  • 打印线程测试“a==3”
  • 打印线程测试“b==2”
  • 混乱的2

  • 注意,如果没有volatile,您甚至可以得到更古怪的答案,比如打印线程看到“a==1,b==3”

    你的书面陈述是错误的。它们不表示
    if
    中的条件。另外,您可能希望首先在局部变量中捕获它们的值,然后仅对局部变量进行操作。对不起,您所说的“您的打印语句是错误的。它们不代表if中的条件”是什么意思?它们都打印
    ]混淆1:a=1,b=3
    。非常好。感谢您这是一个强制性的提醒,“我认为volatile会使每个线程只访问主内存,而不是它们自己的工作内存。”请描述
    volatile
    在一个假设的CPU中的行为,该CPU与现代计算机中的实际CPU工作方式几乎没有相似之处,
    volatile
    实际上并不强制任何东西进入主内存。(这很好。现代CPU上有很多核心间通信,主内存非常慢。如果真正的CPU以这种方式工作,那将是一场灾难!)
    volatile
    在这里有什么区别吗?按照编码方式,两个线程都可以访问相同的变量。如果有什么原因的话,它可能会因为每次修改时的
    直写
    而运行较慢。@JanezKuhar-我不确定“访问变量”是什么意思,但volatile确实排除了一种可能性,正如我在上一句中提到的。当然,volatile确实会影响性能。你说得对,如果使用
    volatile
    ,它就不能打印a=1,b=3,我的错。