首页 > 解决方案 > 在已实现的 Java 代码中需要有关易失性和非易失性概念的帮助?

问题描述

我编写了以下代码来理解 java 中的 volatile 概念,但输出似乎令人困惑而不是澄清概念。欢迎和赞赏更正、澄清和反馈。

package threading;

public class UnSyncRead {
    //volatile static int value = 987;
    static int value = 987;
    public static void main(String[] args) {


        ThreadEx4 t = new ThreadEx4(value);
        t.start();
        for(int i=0;i<4;i++) {
            Thread thread = new Thread( new ThreadEx3(value));
            thread.start();
        }
    }

}

class ThreadEx3 implements Runnable{
private int i;
    public ThreadEx3(int i) {
        this.i=i;
}

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



}

class ThreadEx4 extends Thread{
    private int i;
    public ThreadEx4(int i) {
        this.i=i;
    }
    public void run() {
        ++i;
        System.out.println("changed the value to "+i);
    }
}

该程序给出以下输出

changed the value to 988
12  Thread-1  inside 987
13  Thread-2  inside 987
14  Thread-3  inside 987
15  Thread-4  inside 987

但是,如果我通过执行以下更改并运行代码来修改代码以使其value可变。volatile

public class UnSyncRead {
volatile static int value = 987;
//static int value = 987;
public static void main(String[] args) {


    ThreadEx4 t = new ThreadEx4(value);
    t.start();
    for(int i=0;i<4;i++) {
        Thread thread = new Thread( new ThreadEx3(value));
        thread.start();
    }
}

}

当我在没有 volatile 关键字的情况下运行它时,我得到了完全相同的输出。

changed the value to 988
12  Thread-1  inside 987 
13  Thread-2  inside 987
14  Thread-3  inside 987
15  Thread-4  inside 987 

我的问题是为什么 for 循环中的线程仍在读取value变量 as987和 not的值988,即使在实现 volatile 关键字之后也是如此。

将深深感谢这个问题的答案。

标签: javamultithreadingvolatile

解决方案


这与多线程完全无关,这是一个更基本的问题。

class ThreadEx4 extends Thread{
    private int i;
    public ThreadEx4(int i) {
        this.i=i;
    }
    public void run() {
        ++i;
        System.out.println("changed the value to "+i);
    }
}

您在此处更改私有变量i,而不是全局static字段。

Java 通过值传递事物。所以当你说new ThreadEx4(myInteger)的时候,构造函数会收到里面的数字myInteger。它对其本地副本所做的任何事情都不会产生任何影响myInteger

要继续您的多线程实验,请摆脱局部变量并执行

class Ex4 extends Runnable {
      @Override
      public void run(){
          int newValue = ++UnSyncRead.value;
          System.out.println("changed the value to "+newValue);
      }
}
// and the same for the other runnables

推荐阅读