为什么volatile在比较期间不能解决数据竞争

问题描述 投票:2回答:1

我正在尝试从此处尝试多线程和以下示例:https://docs.oracle.com/javase/specs/jls/se10/html/jls-8.html#jls-8.3.1.4

我已经在下面发布了我的代码。您能否帮助我了解为什么发生“ if (x < y) {”而不是“ if (y > x) {”的数据竞争?

我正在使用openjdk-14.0.1

Linux void-MS-7678 5.4.0-29-generic#33-Ubuntu SMP Wed Apr 29 14:32:27 UTC 2020 x86_64 x86_64 x86_64 GNU / Linux

代码:

public class Main {
    public static void main(String[] args) {
        DataRace dr = new DataRace();
        Thread t1 = new Thread(()-> {
            for (int i = 0; i < 100_000; i++) {
                dr.increment();
            }
        });

        Thread t2 = new Thread(()-> {
            for (int i = 0; i < 100_000; i++) {
                dr.check();
            }
        });

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

    private static class DataRace {
        private volatile int x = 0, y = 0;

        public void increment() {
            x++;
            y++;
        }

        public void check() {
            // System.out.println("x=" + x + " y="+ y); // - NO ISSUES
            // if (y > x) { - NO ISSUES
            // if (x < y) { - ISSUES
            if (x < y) {
                System.out.println("DataRace detected: x < y");
            }
        }
    }
}

输出:

/home/void/.jdks/openjdk-14.0.1/bin/java -javaagent:/home/void/Development/idea-IC-183.4588.61/lib/idea_rt.jar=46411:/home/void/Development/idea-IC-183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /home/void/Development/multithreading/out/production/classes Main
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y
DataRace detected: x < y

Process finished with exit code 0
java multithreading volatile
1个回答
3
投票

比较if (x < y) {不是原子的。

  • [t2加载x进行比较
  • t2停止工作
  • [t1递增xy
  • t1停止
  • t2开始
  • [t2加载y进行比较
  • 因为x是旧值,y是新值,递增,x < ytrue

这里是如何使用synchronized解决该问题的示例:

class Main {
    public static void main(String[] args) {
        DataRace dr = new DataRace();
        Thread t1 = new Thread(()-> {
            for (int i = 0; i < 100_000; i++) {
                dr.increment();
            }
        });

        Thread t2 = new Thread(()-> {
            for (int i = 0; i < 100_000; i++) {
                dr.check();
            }
        });

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

    private static class DataRace {
        private volatile int x = 0, y = 0;

        public synchronized void increment() {
            x++;
            y++;
        }

        public void check() {
            // System.out.println("x=" + x + " y="+ y); // - NO ISSUES
            // if (y > x) { - NO ISSUES
            // if (x < y) { - ISSUES
            boolean xSmallerY = false;
            synchronized (this) {
                xSmallerY = x < y;
            }
            if (xSmallerY) {
                System.out.println("DataRace detected: x < y");
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.