java - 为什么在 Java 内存模型中两次写入同一个变量会发生冲突?

标签 java multithreading

不存在数据竞争顺序一致性的先决条件。 数据竞争 是由冲突 访问引起的。如果至少有一个访问是写入,则对同一变量的两次访问冲突

请参阅以下来自 JLS7 的引用以供引用。

我理解这种情况下的定义,其中一个操作是读访问,另一个操作是写访问。但是,如果对同一个变量有两个写操作,我不明白为什么需要它(对于内存模型)。

问题保证顺序一致性的理由是什么? 发生在之前的关系?


§17.4.1: [..] Two accesses to (reads of or writes to) the same variable are said to be conflicting if at least one of the accesses is a write.

§17.4.5: [..] When a program contains two conflicting accesses that are not ordered by a happens-before relationship, it is said to contain a data race. [..] A program is correctly synchronized if and only if all sequentially consistent executions are free of data races. If a program is correctly synchronized, then all executions of the program will appear to be sequentially consistent.

最佳答案

如果两个写访问不在 happens-before 关系中,则未指定哪个将最后发生,即哪个分配获胜。例如程序

static int x;
static int y;

public static void main(String[] args) {
    Thread t1 = new Thread() {
        @Override public void run() {
            x = 1;
            y = 1;
        }
    };
    Thread t2 = new Thread() {
        @Override public void run() {
            y = 2;
            x = 2;
        }
    };
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(x + "" + y);
}

可能会打印 11、12、21 或 22,即使唯一的数据竞争是在写入之间,并且 12 无法通过顺序一致的执行获得。

关于java - 为什么在 Java 内存模型中两次写入同一个变量会发生冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18560046/

相关文章:

c++ - 获取/释放语义重新排序

c++ - OpenGL函数需要调用两次才能生效

java - 可以跟踪我在字符串中的位置、空白并停止循环的方法

java - Travis CI 构建失败

java - 递归方法返回从 int 到 0 的数字

c++ - 带有 Qt 的 std::thread

java - 线程停止执行

java - EDT、异步、同步

Java使用extends访问变量

java - Firebase Android 在长按的 ListView 中删除节点键