Bob*_*r02 4 java concurrency multithreading locking volatile
让我们考虑一下 Java 中的以下标准同步:
public class Job {
private Lock lock = new ReentrantLock();
public void work() {
lock.lock();
try {
doLotsOfWork();
} finally {
lock.unlock();
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据Javadoc,我理解这相当于synchronized块。我正在努力了解这实际上是如何在较低级别上执行的。
Lock有一个易失性的状态,在调用lock()它时会执行易失性读取,然后在释放时执行易失性写入。对一个对象的状态进行写入如何确保可能涉及许多不同对象的指令doLotsOfWork不会乱序执行?
或者想象一下 doLotsOfWork 实际上被 1000 多行代码取代。显然,编译器无法提前知道锁内某处存在 volatile,因此它需要停止对指令重新排序。lock/unlock那么,即使它是围绕单独对象的易失性状态构建的,如何保证发生之前呢?
好吧,如果我理解正确的话,那么你的答案就在这里。易失性写入和读取会引入内存屏障:LoadLoad、LoadStore等,禁止重新排序。在 CPU 级别,这被转换为实际的内存屏障,例如mfence或lfence(CPU 也通过其他一些机制强制不重新排序,因此您可能还会在机器代码中看到其他内容)。
这是一个小例子:
i = 42;
j = 53;
[StoreStore]
[LoadStore]
x = 1; // volatile store
Run Code Online (Sandbox Code Playgroud)
i和j分配可以在 then 之间重新排序,但它们不能与x=1x 或换句话说i and j不能低于 x。
同样适用于volatile reads.
对于您的示例,内部的每个操作都doLotsOfWork可以根据编译器的意愿重新排序,但不能使用lock operations.
另外,当您说编译器无法知道存在 a 时volatile read/write,您就有点错误了。它必须知道这一点,否则就没有其他方法来阻止这些重新排序。
另外,最后一点:从 jdk-8 开始,您可以通过Unsafe提供非易失性之外的方法来强制执行非重新排序。
| 归档时间: |
|
| 查看次数: |
468 次 |
| 最近记录: |