问题标签 [memory-barriers]

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 投票
8 回答
11771 浏览

c++ - 用户空间中的内存障碍?(Linux,x86-64)

在内核端设置内存屏障很容易:由于 Linux 内核头文件,宏 mb、wmb、rmb 等始终存在。

如何在用户端做到这一点?

0 投票
5 回答
526 浏览

c# - 内存屏障和大型结构?

假设我有一个由 100 个字节组成的结构。我对以下代码有什么保证?

内存模型是否保证放置内存屏障后 100 字节的复制将完成?还是内存屏障仅适用于处理器架构大小的类型?(32 位为 4 个字节,64 位为 8 个字节)。
这就是volatile关键字仅适用于原始类型的原因吗?(如果我将一个 8 字节的成员声明为 volatile,这意味着将使用互锁的 instrinct 来更改它的值?[因为在 32 位机器上不能保证大于 4 字节的类型的原子性])。

我希望我足够清楚.. :)
谢谢

0 投票
2 回答
26602 浏览

multithreading - 我如何理解读内存屏障和易失性

某些语言提供了一个volatile修饰符,该修饰符被描述为在读取支持变量的内存之前执行“读取内存屏障”。

读内存屏障通常被描述为一种确保 CPU 在屏障之后执行读取请求之前已执行屏障之前请求的读取的方法。然而,使用这个定义,似乎仍然可以读取陈旧的值。换句话说,按一定顺序执行读取似乎并不意味着必须咨询主存储器或其他 CPU,以确保后续读取的值实际上反映了系统中在读屏障时的最新值或在读取屏障之后随后写入的值。阅读障碍。

那么,volatile 真的保证读取的是最新的值还是只是(喘气!)读取的值至少与屏障之前的读取一样是最新的?还是其他的解释?这个答案的实际意义是什么?

0 投票
1 回答
4644 浏览

.net - 何时在 .NET 中使用 lock 与 MemoryBarrier

在 .NET 中,关键字是andlock周围的语法糖,所以你可以说这段代码Monitor.EnterMonitor.Exit

是相同的

然而 .NET 框架还包括MemoryBarrier以类似方式工作的类

我很困惑什么时候想使用Thread.MemoryBarrier/lock版本Monitor一个线程教程让我更加困惑,它指出它们的功能相同。

据我所见,明显的区别是不需要锁定对象,我想使用Monitor它可以MemoryBarrier在单个线程上跨线程执行某些操作。

我的直觉告诉我,另一个关键区别是MemoryBarrier仅针对变量而不针对方法。

最后,这与现有问题何时在线程安全锁定代码中使用 'volatile' 或 'Thread.MemoryBarrier()' 无关?(C#),因为它专注于volatile我理解其用法的关键字。

0 投票
1 回答
1250 浏览

c++ - _ReadWriteBarrier 如何向上传播调用树?

我正在查看Visual C++ 的 _ReadWriteBarrier 内在文档中的这段文字:

在 Visual C++ 编译器的过去版本中,_ReadWriteBarrier 和 _WriteBarrier 函数仅在本地强制执行,不会影响调用树上的函数。在 Visual C++ 2005 及更高版本中,这些函数在调用树中一直强制执行。

我了解障碍在函数中的作用,但“调用树”似乎暗示foo()调用函数的函数bar()可以知道是否bar()包含障碍。在 VC2005 中实际改变了什么来启用这个......调用约定/ABI,编译器完成的一些全局分析,还是什么?

0 投票
3 回答
583 浏览

java - Java LockSupport 内存一致性

Java 6 API 问题。调用是否与刚刚未停放的线程中的返回LockSupport.unpark(thread)发生之前的关系?LockSupport.park我强烈怀疑答案是肯定的,但 Javadoc 似乎没有明确提及。

0 投票
5 回答
1404 浏览

java - 链接构造函数时,JVM 的隐式内存屏障如何表现?

参考我之前关于未完全构造的对象的问题,我还有第二个问题。正如 Jon Skeet 指出的那样,构造函数末尾有一个隐式内存屏障,可确保final所有线程都可以看到字段。但是如果一个构造函数调用另一个构造函数呢?他们每个人的末尾是否有这样的内存屏障,或者仅在首先被调用的那个末尾?也就是说,当“错误”的解决方案是:

正确的是工厂方法版本:

以下是否也有效?

更新:基本问题是this()保证实际调用上面的私有构造函数(在这种情况下,预期的地方会有障碍,一切都是安全的),或者私有构造函数是否有可能作为一个内联到公共构造函数中优化以保存一个内存屏障(在这种情况下,直到公共构造函数结束时才会有屏障)?

规则是否在this()某处精确定义?如果不是,那么我认为我们必须假设允许内联链式构造函数,并且可能一些 JVM 甚至可能javac正在这样做。

0 投票
6 回答
2324 浏览

c++ - 线程同步 101

以前我写过一些非常简单的多线程代码,而且我一直都知道,在我正在做的事情中,任何时候都可能会发生上下文切换,所以我一直保护通过共享变量的访问一个 CCriticalSection 类,它进入构造的关键部分并使其处于破坏状态。我知道这是相当激进的,我经常进入和离开关键部分,有时甚至非常严重(例如,在函数开始时,我可以将 CCriticalSection 放在更紧凑的代码块中)但我的代码没有崩溃并且运行速度足够快.

在工作中,我的多线程代码需要更紧密,只需在所需的最低级别锁定/同步。

在工作中我试图调试一些多线程代码,我遇到了这个:

现在,m_bSomeVariable是一个 Win32 BOOL(非易失性),据我所知,它被定义为一个 int,并且在 x86 上读取和写入这些值是一条指令,并且由于上下文切换发生在指令边界上,所以没有必要用于将此操作与关键部分同步。

我在网上做了一些研究,看看这个操作是否不需要同步,我想出了两个场景:

  1. CPU 实现乱序执行或者第二个线程在不同的内核上运行,并且更新的值没有写入 RAM 以供其他内核查看;和
  2. int 不是 4 字节对齐的。

我相信数字 1 可以使用“volatile”关键字来解决。在 VS2005 及更高版本中,C++ 编译器使用内存屏障围绕访问此变量,确保在使用之前始终将变量完全写入/读取到主系统内存。

数字 2 我无法验证,我不知道为什么字节对齐会产生影响。我不知道 x86 指令集,但是否mov需要给定一个 4 字节对齐的地址?如果不需要,您是否需要使用指令组合?那会引入问题。

所以...

问题 1:使用“volatile”关键字(隐式使用内存屏障并提示编译器不要优化此代码)是否使程序员无需在读取 / 之间同步 x86/x64 变量上的 4 字节/8 字节写操作?

问题 2:是否有明确要求变量是 4 字节/8 字节对齐的?

我对我们的代码和类中定义的变量做了更多的研究:

现在,对我来说,这似乎太过分了。我认为关键部分在进程之间同步线程,所以如果你有一个你可以输入它并且该进程中没有其他线程可以执行。对于您要保护的每个变量,不需要一个临界区,如果您处于临界区,那么没有其他东西可以打断您。

我认为唯一可以从关键部分外部更改变量的是进程是否与另一个进程共享内存页面(你可以这样做吗?)并且另一个进程开始更改值。互斥体在这里也有帮助,命名互斥体是跨进程共享的,还是只有同名的进程?

问题 3:我对关键部分的分析是否正确,是否应该重写此代码以使用互斥锁?我看过其他同步对象(信号量和自旋锁),它们更适合这里吗?

问题 4:关键部分/互斥体/信号量/自旋锁最适合哪里?也就是说,它们应该应用于哪个同步问题。选择一个而不是另一个会带来巨大的性能损失吗?

在我们讨论的过程中,我读到自旋锁不应该在单核多线程环境中使用,只能在多核多线程环境中使用。所以,问题 5:这是错的,或者如果不是,为什么是对的?

提前感谢您的任何回复:)

0 投票
3 回答
6345 浏览

c - 原子引用计数共享不可变数据是否需要内存屏障?

我有一些不可变的数据结构,我想使用引用计数来管理它们,在 SMP 系统上的线程之间共享它们。

发布代码如下所示:

atomic_dec需要内存屏障吗?如果是这样,什么样的内存屏障?

附加说明:该应用程序必须在 PowerPC 和 x86 上运行,因此欢迎提供任何特定于处理器的信息。我已经知道 GCC atomic builtins。至于不变性,引用计数是唯一在对象的持续时间内发生变化的字段。

0 投票
6 回答
1794 浏览

c++ - 编译器围绕互斥边界重新排序?

假设我有自己的非内联函数 LockMutex 和 UnlockMutex,它们在内部使用了一些适当的互斥锁 - 例如 boost。编译器如何知道不对 LockMutex 和 UnlockMutex 调用的其他操作重新排序?它不可能知道我将如何在其他编译单元中实现这些功能。

ps:一个应该使用类的实例来持有锁以保证解锁。为了简化示例,我忽略了这一点。