- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在 Java 中,当我们有两个线程共享以下变量时:
int a;
volatile int b;
如果线程 1 执行:
a = 5;
b = 6;
然后在这两条指令之间插入一个 StoreStore 屏障,并将“a”刷新回主内存。
现在如果线程 2 执行:
if(b == 6)
a++;
在两者之间插入一个 LoadLoad 屏障,我们可以保证如果“b”的新值可见,那么“a”的新值也可见。但实际上这是如何实现的呢? LoadLoad 是否会使 CPU 缓存/寄存器失效?或者只是指示 CPU 再次从 CPU 读取从 volatile 中读取的变量值?
我找到了关于 LoadLoad barrier ( http://gee.cs.oswego.edu/dl/jmm/cookbook.html ) 的信息:
LoadLoad Barriers The sequence: Load1; LoadLoad; Load2 ensures that Load1's data are loaded before data accessed by Load2 and all subsequent load instructions are loaded. In general, explicit LoadLoad barriers are needed on processors that perform speculative loads and/or out-of-order processing in which waiting load instructions can bypass waiting stores. On processors that guarantee to always preserve load ordering, the barriers amount to no-ops.
但它并没有真正解释这是如何实现的。
最佳答案
我将举一个例子来说明这是如何实现的。您可以阅读更多详细信息here .对于您指出的 x86 处理器,LoadLoad 最终成为空操作。在我链接的文章中,Mark 指出
Doug lists the StoreStore, LoadLoad and LoadStore
所以本质上,唯一需要的障碍是用于 x86 架构的 StoreLoad。那么这是如何在低层次上实现的呢?
这是博客的摘录:
这是它为 volatile 和非 volatile 读取生成的代码:
nop ;*synchronization entry
mov 0x10(%rsi),%rax ;*getfield x
对于 volatile 写入:
xchg %ax,%ax
movq $0xab,0x10(%rbx)
lock addl $0x0,(%rsp) ;*putfield x
lock
指令是 Doug 的食谱中列出的 StoreLoad。但是 lock 指令还会将所有读取与其他进程同步为 listed
Locked instructions can be used to synchronize data written by one processor and read by another processor.
这减少了必须为易变负载发出 LoadLoad LoadStore 障碍的开销。
综上所述,我将重申 assylias 指出的内容。它发生的方式对开发人员来说不应该很重要(如果您对处理器/编译器实现者感兴趣,那是另一回事)。 volatile
关键字是一种接口(interface)说明
关于java - LoadLoad barrier 的真正作用是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15360598/
在 Java 中,当我们有两个线程共享以下变量时: int a; volatile int b; 如果线程 1 执行: a = 5; b = 6; 然后在这两条指令之间插入一个 StoreStore
我想在原子和非原子操作之间使用独立内存屏障(我认为无论如何这根本不重要)。我想我理解存储屏障和加载屏障的含义以及 4 种可能的内存重新排序; LoadLoad , StoreStore , LoadS
我是一名优秀的程序员,十分优秀!