java - Java中如何正确使用volatile

标签 java multithreading volatile

我正在研究 Java Thread,当我分析以下修改自 Example 8.3.1.4 的代码时,关键字 volatile 让我感到困惑

public class Volatile {
    public static void main(String[] args){
        MyRunnable1 myRunnable1 = new MyRunnable1();
        MyRunnable2 myRunnable2 = new MyRunnable2();
        Thread t1 = new Thread(myRunnable1);
        Thread t2 = new Thread(myRunnable2);

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

class MyRunnable1 implements Runnable{
    public void run(){
        while(true){
            Test1.one();
        }
    }
}
class MyRunnable2 implements Runnable{
    public void run(){
        while(true){
            Test1.two();
        }
    }
}

class Test1{
    static volatile int i = 0;
    static volatile int j = 0;
    static void one(){
        i ++;
        j ++;
    }

    static void two(){
        System.out.println("i = " + i  + " j = " + j);
    }
}

一个输出段:

i = 60778110 j = 60778116
i = 60778402 j = 60778407
i = 60778630 j = 60778636
i = 60779062 j = 60779079
i = 60779492 j = 60779497
i = 60779784 j = 60779789
i = 60780161 j = 60780169
i = 60780625 j = 60780632
i = 60780936 j = 60780942

我的想法是,由于volatilei++发生在j++之前,它们的初始值为零,修改后的值将立即刷新到主内存,因此 i 线程 t2 看到的任何时候都应该大于 j。然而,输出显示 i 始终低于 j

然后我修改two函数如下:

static void two(){
    System.out.println("j = " + j  + " i = " + i);
}

变化是j先于i输出,然后输出段如下:

j = 47324409 i = 47324412
j = 47324587 i = 47324593
j = 47324808 i = 47324813
j = 47324991 i = 47324996
j = 47325193 i = 47325196
j = 47325347 i = 47325353

j 总是低于i,这让我很惊讶。

我的想法是 j 较低,因为它首先连接,一段时间后 i 连接,在时间间隔期间 one 函数执行导致 i 增加。

所以第一个连接的值会比第二个连接的低,对吗?提前致谢!

最佳答案

你猜对了。不同之处在于 println 调用的参数分 3 个步骤构建:

  1. 构建字符串 s = "i = "+ i
  2. 构建字符串 s = s + "j = "
  3. 构建字符串 s = s + j

并且在 Runnable2 执行此操作时,尤其是在步骤 1 之后和最终打印之前,Runnable2 正忙于递增值。这会导致您看到的行为。

这不是volatile的问题。如果你想让i和j同步,你必须同步类Test1的方法。

关于java - Java中如何正确使用volatile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38811080/

相关文章:

arrays - 将 volatile 数组传递给 strncpy

java - 调整数组大小图标

java - WELD-001408 不满足的依赖关系 - 找不到根本原因

multithreading - Tensorflow 中的 A3C - 我应该使用线程还是分布式 Tensorflow API

java - 更改线程的目标核心

java.util.ConcurrentModificationException : Unexpected List modification while multithreading?

c++ - 为什么volatile静态成员初始化会产生重定义编译错误?

c++ - 所有全局变量都应该是 volatile 限定的吗?

java - 如何对泛型类型列表进行 instanceof 检查?

java - 如何将 List<List<String>> 转换为 String[][]?