gpt4 book ai didi

java - 指令重新排序如何导致并发问题

转载 作者:行者123 更新时间:2023-12-02 21:18:18 26 4
gpt4 key购买 nike

我正在阅读有关 JMM(Java 内存模型)的内容,我可以理解缓存变量的刷新如何导致其他线程进行脏读。还有人提到,指令重新排序可能会导致并发问题,尽管我理解指令重新排序的含义,但我不明白它如何导致并发问题。

例如,假设线程 t1 在启动 test1() 时获取了锁,现在即使编译器已进行一些优化并且由于 z = 4; 存在一些重新排序; 要么上升要么下降,现在因为 t2 在 t1 释放之前不会获得 test2() 的锁定,那么如何在 test1()< 中重新排序 (甚至在 test2() 中)可能会导致并发问题/错误?

public class Testing {
private int z = 2;

public synchronized void test1(){
//some statement..
z = 4;
//some statement..
}

public synchronized void test2(){
//some statement..
System.out.println(z);
//some statement..
}
}

<小时/>我知道在正确的同步重新排序后不会导致问题,但是如果没有同步,即使编译器没有优化和重新排序,仍然有可能出现并发问题,对吗?需要明确的是,我指的是 this链接,我无法理解他们关于重新排序后并发问题的观点,因为就像我说的,如果没有同步,那么即使没有任何重新排序,并发问题仍然可能出现。

编辑:请丢弃我的代码片段,因为在查看评论后,它现在不太适用,我更新的问题如上所述。

最佳答案

您不会看到使用单个变量重新排序的问题。但是拿两个......

int foo = 0;
boolean isFooSet = false;
...
// thread 1
foo = 42;
isFooSet = true;
...
// thread 2
while (!isFooSet) {/*waste some time*/} // we wait until the flag is set in the other thread
System.out.println(42/foo); //we can actually divide by zero here

因此,虽然线程 1 在 isFooSet 之前看到 foo 设置,但线程 2 可以以相反的方式看到它们,这使得标记 isFooSet 无用.

请注意,如果不重新排序,此代码将是完全安全的(即除以零),例如,您可以看到 isFooSet 是否被声明为 volatile,防止在写入isFooSet之后将写入移动到foo它还解决了另一个与非重新排序相关的可见性问题,但这是一个不同的故事

关于java - 指令重新排序如何导致并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44078354/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com