作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Java 8 中,三个内存屏障指令被添加到 Unsafe
类(source):
/**
* Ensures lack of reordering of loads before the fence
* with loads or stores after the fence.
*/
void loadFence();
/**
* Ensures lack of reordering of stores before the fence
* with loads or stores after the fence.
*/
void storeFence();
/**
* Ensures lack of reordering of loads or stores before the fence
* with loads or stores after the fence.
*/
void fullFence();
如果我们用以下方式定义内存屏障(我认为或多或少容易理解):
Consider X and Y to be operation types/classes that are subject for reordering,
X_YFence()
is a memory barrier instruction that ensures that all operations of type X before the barrier completed before any operation of type Y after the barrier is started.
Unsafe
到这个术语:
loadFence()
变成 load_loadstoreFence()
; storeFence()
变成 store_loadStoreFence()
; fullFence()
变成 loadstore_loadstoreFence()
; load_storeFence()
、
store_loadFence()
、 0x2513431 和 132513432 ?
最佳答案
概括
CPU 内核具有特殊的内存排序缓冲区,以帮助它们进行乱序执行。这些可以(并且通常是)单独用于加载和存储:用于加载顺序缓冲区的 LOB 和用于存储顺序缓冲区的 SOB。
为 Unsafe API 选择的防护操作是基于以下假设选择的:底层处理器将具有单独的加载顺序缓冲区(用于重新排序加载)、存储顺序缓冲区(用于重新排序存储)。
因此,基于此假设,从软件的角度来看,您可以向 CPU 请求以下三件事之一:
failure
的缓存线最初由 CPU 1 所有,而包含
shutdown
的缓存线最初由 CPU 0 所有。
// CPU 0:
void shutDownWithFailure(void)
{
failure = 1; // must use SOB as this is owned by CPU 1
shutdown = 1; // can execute immediately as it is owned be CPU 0
}
// CPU1:
void workLoop(void)
{
while (shutdown == 0) { ... }
if (failure) { ...}
}
failure
的值 1 写入存储顺序缓冲区,同时发送缓存一致性消息以获取对缓存行的独占访问。然后它将继续执行下一条指令(在等待独占访问时)并立即更新
shutdown
标志(该缓存线已由 CPU0 独占所有,因此无需与其他内核协商)。最后,当它稍后收到来自 CPU1 的无效确认消息(关于
failure
)时,它将继续处理
failure
的 SOB 并将该值写入缓存(但现在顺序颠倒了)。
// CPU 0:
void shutDownWithFailure(void)
{
failure = 1; // must use SOB as this is owned by CPU 1
SFENCE // next instruction will execute after all SOBs are processed
shutdown = 1; // can execute immediately as it is owned be CPU 0
}
// CPU1:
void workLoop(void)
{
while (shutdown == 0) { ... }
if (failure) { ...}
}
shutdown
在通往 CPU 1 的途中无法超过
failure
,并专注于另一侧。即使在商店围栏的存在下,也有发生错误的情况。考虑
failure
在两个缓存(共享)中的情况,而
shutdown
仅存在于 CPU0 的缓存中并由其独占拥有。不好的事情可能会发生如下:
failure
;作为缓存一致性协议(protocol)的一部分,它还向 CPU1 发送消息以使其共享缓存行的副本无效。 failure
的 SOB 提交。 shutdown
并且(意识到它缺少该值)发送缓存一致性消息以读取该值。 failure
无效,并立即发送确认。注意:这是使用失效队列实现的,因此实际上它只是输入一个注释(在其 LOB 中分配一个条目)以稍后进行失效,但在发送确认之前实际上并不执行它。 failure
的确认,并通过 SFENCE 进入下一条指令 shutdown
值并将其提交到其本地缓存,继续下一行。 failure
值,但由于无效队列(LOB 注释)尚未处理,它使用其本地缓存中的值 0(不进入 if 块)。 failure
更新为1,但是已经来不及了... // CPU 0:
void shutDownWithFailure(void)
{
failure = 1; // must use SOB as this is owned by CPU 1
SFENCE // next instruction will execute after all SOBs are processed
shutdown = 1; // can execute immediately as it is owned be CPU 0
}
// CPU1:
void workLoop(void)
{
while (shutdown == 0) { ... }
LFENCE // next instruction will execute after all LOBs are processed
if (failure) { ...}
}
loadFence() becomes load_loadstoreFence();
load_storeFence() becomes ???
关于Java 8 不安全 : xxxFence() instructions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23603304/
在 Java 8 中,三个内存屏障指令被添加到 Unsafe 类(source): /** * Ensures lack of reordering of loads before the fenc
我是一名优秀的程序员,十分优秀!