有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

没有同步或易失性的java内存可见性

如果没有“synchronized”或“volatile”关键字,那么一个线程所做的更改将永远不会被另一个线程看到(或不显示),这是正确的吗?我在多核平台上多次运行以下程序,结果不同。有时程序永远不会终止,这是预期的场景。但有时它会打印“1”
JDK:jdk1。8.0_73
OS:CentOS Linux 7.1.1503版

public class VolatileTest implements Runnable {
    private int i = 0;

    public void run() {
        i++;
        i++;
    }

    public int get() {
        return i;
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        VolatileTest volatileTest = new VolatileTest();
        executorService.execute(volatileTest);
        while (true) {
            int i = volatileTest.get();
            if (i % 2 != 0) { // 
                System.out.format("i: %s \n", i);
                System.exit(0);
            }
        }
    }
}

共 (2) 个答案

  1. # 1 楼答案

    Is it correct to say without "synchronized" or "volatile" keyword, changes made by one thread will never be seen by another (or non-deterministic)?

    这不正确,这个问题已经得到了回答(this

    run方法不是原子的/线程安全的/同步的,因此,赋值int i = volatileTest.get();可以得到0到2的值,这很容易理解。为了达到你想要的效果,你应该获得一个lock并在双增量后重新分配它,或者只把关键字synchronized放在方法签名中

  2. # 2 楼答案

    volatileTest.get()的输出可以是0, 1, or 2,因为没有同步,并且run方法不是原子的。此外,每个i++操作都不是原子操作

    因此,这两种情况都适用:

    1. 打印1退出:一旦i++操作完成,get的结果是1
    2. 两条i++指令都已完成,get()返回2,因此陷入无限循环