gpt4 book ai didi

Java - Lock 如何保证 happens-before 关系?

转载 作者:搜寻专家 更新时间:2023-11-01 02:37:37 25 4
gpt4 key购买 nike

让我们考虑以下 Java 中的标准同步:

public class Job {
private Lock lock = new ReentrantLock();

public void work() {
lock.lock();
try {
doLotsOfWork();
} finally {
lock.unlock();
}
}
}

我理解,基于 Javadoc,这等同于 synchronized block 。我正在努力了解这实际上是如何在较低级别上执行的。

Lock 有一个易变的状态,在调用 lock() 时它会执行 volatile 读取,然后在释放时它会执行 volatile 写入。写入一个对象的状态如何确保 doLotsOfWork指令(可能涉及许多不同的对象)不会乱序执行?

或者想象一下,doLotsOfWork 实际上被替换为 1000 多行代码。显然,编译器无法提前知道锁内某处存在 volatile,因此它需要停止对指令进行重新排序。那么,如何保证 lock/unlock 的 happens-before,即使它是围绕一个单独对象的 volatile 状态构建的?

最佳答案

好吧,如果我理解正确,那么你的答案是 here . volatile 写入和读取引入了内存障碍:LoadLoadLoadStore禁止 重新排序。在 CPU 级别,这被转换为实际的内存屏障,如 mfencelfence(CPU 也通过其他一些机制强制非重新排序,因此您可能会在机器代码也是如此)。

这是一个小例子:

i = 42;
j = 53;
[StoreStore]
[LoadStore]
x = 1; // volatile store

ij 之间的赋值可以重新排序,但 它们不能 x=1 或者换句话说 i 和 j 不能低于 x。

这同样适用于volatile reads

对于您的示例,doLotsOfWork 中的每个操作都可以按照编译器的要求重新排序,但不能使用锁定操作 重新排序。

另外当你说编译器不知道有一个volatile read/write时,你有点错了。它必须知道这一点,否则就没有其他方法可以防止这些重新排序。

另外,最后一点:自 jdk-8 以来,您可以通过 Unsafe 强制执行非重新排序,它提供了除 volatile 之外的方法。

关于Java - Lock 如何保证 happens-before 关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43557339/

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