问题标签 [memory-fences]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
1211 浏览

java - 使用 final 字段的成本

我们知道将字段设置为 final 通常是一个好主意,因为我们获得了线程安全性和不变性,这使得代码更容易推理。我很好奇是否有相关的性能成本。

Java 内存模型保证了这一点final Field Semantics

只有在对象完全初始化后才能看到对该对象的引用的线程可以保证看到该对象的最终字段的正确初始化值。

这意味着对于这样的课程

每当线程 1 创建这样的实例时

线程 2 看到了

它必须打印 43。没有final修饰符,JIT 或 CPU 可以重新排序存储(首先存储X.instance然后设置a=43),线程 2 可以看到默认初始化值并打印 0。

当 JIT 看到final它时,它显然会避免重新排序。但它也必须强制 CPU 服从命令。是否存在相关的性能损失?

0 投票
4 回答
6692 浏览

java - Java 8 不安全:xxxFence() 指令

在 Java 8 中,三个内存屏障指令被添加到Unsafe类(source):

如果我们用以下方式定义内存屏障(我认为这或多或少容易理解):

将 X 和 Y 视为需要重新排序的操作类型/类,

X_YFence()是一条内存屏障指令,它确保屏障之前的所有类型 X 的操作在屏障开始之后的任何类型 Y 的操作之前完成。

我们现在可以将屏障名称“映射”Unsafe到这个术语:

  • loadFence()变成load_loadstoreFence();
  • storeFence()变成store_loadStoreFence();
  • fullFence()变成loadstore_loadstoreFence();

最后,我的问题是- 为什么我们没有load_storeFence(),store_loadFence()和?store_storeFence()load_loadFence()

我的猜测是——它们并不是真的需要,但我现在不明白为什么。所以,我想知道不添加它们的原因。对此的猜测也是受欢迎的(希望这不会导致这个问题因为基于意见而偏离主题)。

提前致谢。

0 投票
1 回答
346 浏览

multithreading - pthreads v. SSE 弱内存排序

x86_64 上的 Linux glibc pthread 函数是否充当弱排序内存访问的围栏?(pthread_mutex_lock/unlock 是我感兴趣的确切功能)。

SSE2 提供了一些具有弱内存排序的指令(特别是 movntps 等非临时存储)。如果您正在使用这些指令并希望保证另一个线程/核心看到一个排序,那么我知道您需要一个明确的栅栏,例如,一个 sfence 指令。

通常,您确实希望 pthread API 能够适当地充当围栏。但是,我怀疑 x86 上的普通 C 代码不会生成弱排序的内存访问,所以我不确定 pthreads 需要充当弱排序访问的围栏。

通读 glibc pthread 源代码,最终使用“lock cmpxchgl”实现互斥锁,至少在非竞争路径上是这样。所以我猜我需要知道的是该指令是否充当 SSE2 弱排序访问的屏障?

0 投票
4 回答
5382 浏览

c++ - x86(_64) 上的原子计数器和自旋锁的成本

前言

我最近遇到了一些同步问题,这导致我使用自旋锁原子计数器。然后我又搜索了一下,这些是如何工作的,并找到了std::memory_order和内存屏障(mfence,lfencesfence)。

所以现在,似乎我应该对自旋锁使用获取/释放,对计数器使用放松

一些参考

x86 MFENCE - 内存围栏
x86 LOCK - 断言 LOCK# 信号

问题

这三个操作的机器代码(编辑:见下文)是什么(lock = test_and_set,unlock = clear,increment = operator++ = fetch_add),默认(seq_cst)内存顺序和获取/释放/放松(按这些顺序)三个操作)。有什么区别(哪些内存屏障在哪里)和成本(多少 CPU 周期)?

目的

我只是想知道我的旧代码(未指定使用的内存顺序 = seq_cst)到底有多糟糕,以及我是否应该创建一些class atomic_counter派生自std::atomic但使用宽松的内存排序 (以及在某些地方使用获取/释放而不是互斥锁的良好自旋锁)。 ..或使用来自boost库的东西——到目前为止我一直避免boost)

我的知识

到目前为止,我确实理解自旋锁保护的不仅仅是它本身(但也保护了一些共享资源/内存),因此,必须有一些东西可以使多个线程/核心的一些内存视图保持一致(即那些获取/释放和内存栅栏) ) . 原子计数器只为自己而存在,只需要那个原子增量(不涉及其他内存,我读它时并不真正关心它的值,它信息丰富,可能是几个周期的旧,没问题)。有一些LOCK前缀和一些指令,比如xchg隐含地拥有它。我的知识到此结束,我不知道缓存和总线是如何真正工作的以及背后是什么(但我知道现代 CPU 可以重新排序指令,并行执行它们并使用内存缓存和一些同步)。谢谢你的解释。

PS:我现在有旧的32位PC,只能看到lock addl和简单xchg,没有别的-所有版本看起来都一样(解锁除外),memory_order在我的旧PC上没有区别(除了解锁,释放使用move而不是xchg)。对于 64 位 PC 来说会是这样吗?(编辑:见下文)我必须关心内存顺序吗?(回答:不,不多,解锁时释放可以节省几个周期,仅此而已。)

编码:

g++ -std=c++11 -O1 -S ( 32bit Cygwin,缩短输出)

x86_64bit 的更新:(mfenceunlock1

0 投票
3 回答
348 浏览

c# - .Net CompareExchange 重新排序

编译器或处理器是否可以重新排序以下指令,以便另一个线程看到a == 0b == 1

假设int a = 0, b = 0;某处。

0 投票
3 回答
273 浏览

java - Java 等价于 Thread.MemoryBarrier

在Java中,我怎样才能显式触发一个完整的内存围栏/屏障,等于调用

在 C# 中?

我知道,由于 Java 5 对volatile变量的读取和写入导致了完整的内存围栏,但也许有一种(有效的)方法没有volatile.

0 投票
2 回答
402 浏览

multithreading - 如果我们将内存标记为 WC(Write Combined),那么我们是否会自动保持一致性?

正如我们所知,在 x86 架构上自动提供了获取-释放一致性——即所有操作自动排序,没有任何栅栏,不包括第一次存储和下一次加载操作。(如第 34 页 Herb Sutter 所说:https ://onedrive.live.com/view.aspx?resid=4E86B0CF20EF15AD!24884&app=WordPdf&authkey=!AMtj_EflYn2507c )

如果我们将MFENCE(LFENCE+SFENCE)放在它们之间,那么存储就不能重新排序,加载也不能重新排序——即我们提供了顺序一致性

但是如果我们将内存标记为WC(Write Combined),那么我们是否会自动保持一致性而没有任何栅栏,可能是获取释放?

或者如果我们将SSE指令与 WC-memory 一起使用,那么我们就没有任何一致性,如果我们将简单的MOV指令与 WC-memory 一起使用,那么我们就有了获取-释放一致性,不是吗?

0 投票
3 回答
971 浏览

c++ - 内存栅栏会减慢所有 CPU 内核的速度吗?

某处,有一次我读到了记忆栅栏(障碍)。据说内存栅栏会导致多个 CPU 内核之间的缓存同步。

所以我的问题是:

  1. 操作系统(或 CPU 本身)如何知道哪些内核需要同步?

  2. 它是否同步所有 CPU 内核的缓存?

  3. 如果对 (2) 的回答是“是”并且假设同步操作并不便宜,那么使用内存栅栏会减慢我的应用程序未使用的内核吗?例如,如果我有一个单线程应用程序在我的 8 核 CPU 上运行,它会减慢 CPU 的所有其他 7 个内核,因为某些缓存线必须与所有这些内核同步吗?

  4. 上面的问题是完全无知的,围栏的工作方式完全不同吗?

0 投票
1 回答
105 浏览

multithreading - OpenMP 刷新和所有线程的一致性

当某个线程执行omp_set_lock时,会执行隐式刷新。

但这是否意味着在这个特定线程刷新之后,所有其他线程都会将其私有视图更新为共享内存中的值,即使它们自己不执行刷新。还是他们仍会从私人视图中读取值?

0 投票
0 回答
42 浏览

multithreading - 关于 openMP 中的刷新和共享变量

我想知道openMP中线程中共享变量的私有视图何时会被写回内存?

它只会发生在执行刷新(隐式或显式)的地方还是可以在此之前写回?

例如; 最初在 i=0 的某个初始值;

现在时间=0;thread1 更新 i=2 的值;

现在时间=1;如果thread2读取i的值,它是否总是得到i=0,因为thread1没有完成刷新,或者它可能得到i=2