问题标签 [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 投票
3 回答
9383 浏览

opencl - 在 OpenCL 中,mem_fence() 与 barrier() 相比做什么?

不像barrier()(我想我理解),mem_fence()不会影响工作组中的所有项目。OpenCL 规范说(第 6.11.10 节),用于mem_fence()

订购执行内核的工作项的加载和存储。

(因此它适用于单个工作项)。

但是,与此同时,在第 3.3.1 节中,它说:

在工作项内存中具有加载/存储一致性。

所以一个工作项中,内存是一致的。

那么什么样的东西mem_fence()有用呢?它不适用于项目,但在项目中不需要......

请注意,我没有使用原子操作(第 9.5 节等)。mem_fence()是与这些结合使用的想法吗?如果是这样,我很乐意看到一个例子。

谢谢。

规范,供参考。

更新:我可以看到它在 barrier()(隐含地,因为屏障调用mem_fence())一起使用时是如何有用的——但肯定有更多,因为它是单独存在的?

0 投票
2 回答
366 浏览

c# - 可以基于 CPU 架构在运行时使用条件代码吗?

我正在使用.Net 4.5(预览... 4 就这个问题而言很好)。我正在做线程工作。

根据我的研究,我知道 x86 CPU 具有强大的内存模型,这意味着写入不会被重新排序。这使得释放锁是安全的。对于内存模型较弱的 Itanium CPU 而言,情况并非如此。

我了解易失性、内存障碍和执行重新排序原则。

理想情况下,如果CPU 是 Itanium,我需要在关键点插入内存屏障,但如果它是 x86,则不需要。是否可以动态地执行此操作,就像 JIT 处理的运行时编译器指令一样?

如果没有,我意识到我需要为这两个平台分别构建。在这种情况下,在没有 2 组 C# 文件的情况下执行此操作的最优雅方法是什么,而只需更改目标?

0 投票
2 回答
245 浏览

c# - 延迟加载和Thread.MemoryBarrier的使用

当设计一个引用另一个对象的类时,只在第一次使用它时创建被引用的对象可能是有益的,例如使用延迟加载。

我经常使用这种模式来创建一个延迟加载的属性:

然后我在浏览 BCL 的源代码时遇到了这段代码:

据我所知,这些都不是线程安全的。Encoding例如,可以创建多个对象。Encoding我完全明白这一点,并且知道如果创建了一个额外的对象,这不是问题。它是不可变的,很快就会被垃圾收集。

但是,我真的很想了解为什么Thread.MemoryBarrier有必要以及第二个实现与多线程场景中的第一个实现有何不同。

显然,如果线程安全是一个问题,最好的实现可能是使用Lazy<T>

0 投票
2 回答
699 浏览

c# - 需要澄清 Thread.MemoryBarrier()

可能重复:
为什么我们需要 Thread.MemoryBarrier()?

简而言之,来自 O'Reilly 的 C#:

假设方法 A 和 B 在不同的线程上同时运行:


作者说:“障碍 1 和 4 阻止此示例写入“0”。障碍 2 和 3 提供了新鲜度保证:它们确保如果 B 在 A 之后运行,读取 _complete 将评估为真。”

我的问题是:

  1. 为什么需要屏障 4?屏障 1 还不够?
  2. 为什么需要 2 和 3 ?
  3. 据我了解,屏障在其以下指令之后阻止在其位置之前执行指令,我正确吗?
0 投票
1 回答
1574 浏览

java - 内存屏障和 TLB

内存屏障保证数据缓存是一致的。但是,它是否保证 TLB 是一致的?

我看到一个问题,即在线程之间传递 MappedByteBuffer 时,JVM(java 7 update 1)有时会因内存错误(SIGBUS、SIGSEG)而崩溃。

例如

如果没有 Thread.yield(),我偶尔会在 force()、put() 和 C 的 memcpy() 中崩溃,所有这些都表明我试图非法访问内存。使用 Thread.yield() 我没有遇到问题,但这听起来不是一个可靠的解决方案。

有没有人遇到过这个问题?TLB 和内存屏障有什么保证吗?


编辑:操作系统是 Centos 5.7,我已经看到了 i7 和 Dual Xeon 机器上的行为。

我为什么要这样做?因为写入消息的平均时间为 35-100 ns,具体取决于长度,并且使用普通的 write() 并没有那么快。如果我在当前线程中进行内存映射和清理,这需要 50-130 微秒,使用后台线程来完成主线程交换缓冲区大约需要 3-5 微秒。为什么我需要交换缓冲区?因为我正在写入许多 GB 的数据,而 ByteBuffer 的大小不能超过 2 GB。

0 投票
5 回答
2215 浏览

c# - 这是对 Thread.MemoryBarrier() 的正确使用吗?

假设我有一个控制某个循环执行的字段:

我有一个线程正在运行,它的代码如下:

现在,另一个线程可能设置shouldRunfalse,而不使用任何同步机制。

据我了解 Thread.MemoryBarrier(),在 while 循环中进行此调用将阻止我的工作线程获取 的缓存版本shouldRun,并有效地防止发生无限循环。

我对 Thread.MemoryBarrier 的理解是否正确?鉴于我有可以设置shouldRun变量的线程(这不容易更改),这是确保我的循环一旦shouldRun被任何线程设置为 false 就会停止的合理方法吗?

0 投票
3 回答
13435 浏览

c++ - 对共享内存的原子访问

我在多个进程之间有一个共享内存,它以某种方式对内存进行交互。前任:

我想要的是让计数器自动更新/递增。并在该地址上发生内存释放。例如,如果我没有使用共享内存,它将类似于

我如何为随机内存位置实现这一点(解释为 DataBlock 计数器 >above)。我可以保证地址按照架构的要求对齐(x86 linux)

  1. 使更新原子化 - 如何?(即 atomicupdate(addr, newvalue))
  2. 多核的内存同步 - (即 memorysync(addr)) - 我能看到的唯一方法是使用 std::atomic_thread_fence(std::memory_order_release) - 但这将“建立所有原子和宽松原子存储的内存同步排序” - 就是这样对我来说有点矫枉过正——我只想同步计数器位置。欣赏任何想法。
0 投票
2 回答
10490 浏览

c++ - 原子的 C++ 内存屏障

在这方面我是新手。任何人都可以提供以下内存屏障之间差异的简化解释吗?

  • 窗户MemoryBarrier();
  • 栅栏_mm_mfence();
  • 内联汇编asm volatile ("" : : : "memory");
  • 内在的_ReadWriteBarrier();

如果没有简单的解释,一些好的文章或书籍的链接可能会帮助我弄清楚。到目前为止,我只使用由其他人编写的包装这些调用的对象很好,但我希望比我目前的想法有更好的理解,这基本上是按照不止一种方法来实现内存屏障的。

0 投票
3 回答
789 浏览

multithreading - 如果第二个线程等待第一个线程的终止,是否需要内存屏障?

假设线程Alpha正在写入变量A而没有锁定。第二个线程Beta正在等待Alpha终止,然后依次读取变量A

A会不会内容不新鲜?内存写入可以延迟到线程生命周期之外吗?等待线程终止的标准机制不会Alpha隐含地充当内存屏障吗?

更新 1

是否有任何不包括内存屏障的等待示例?

0 投票
4 回答
1502 浏览

c - 使用标志在线程之间进行通信

在 Internet 上,可以找到许多关于volatile在并行编程中使用关键字的争论,有时争论不休。

关于这个主题的更值得信赖的讨论之一似乎是Arch Robison 的这篇文章。他使用的示例是将值从一个线程传递到另一个线程的任务:

线程 1. 计算一个矩阵乘积并将其提供给线程 2,线程 2 用它做其他事情。矩阵是可变M的,标志是volatile指针R

  1. 线程 1 乘以计算矩阵乘积 M 并以原子方式将 R 设置为指向 M。
  2. 线程 2 等到 R!=NULL 然后使用 M 作为一个因子来计算另一个矩阵乘积。

换句话说,M 是一条消息,R 是一个就绪标志。

作者声称,虽然将 R 声明为 volatile 将解决将更改从线程 1 传播到线程 2 的问题,但它不能保证发生这种情况时 M 的值是多少。分配给RM可以重新排序。因此,我们需要在 pthreads 之类的库中同时使用MRvolatile 或使用一些同步机制。

我的问题是,如何在 C 中执行以下操作

1)如何在两个线程之间共享一个标志 - 如何原子地分配给它,确保另一个线程将看到更改并测试另一个线程中的更改。在这种情况下使用 volatile 合法吗?或者某些库能否提供概念上更好或更快的方法,可能涉及内存屏障?

2)如何正确地执行 Robison 的示例,以及如何将矩阵 M 从一个线程发送到另一个线程并安全地进行(最好使用 pthreads 便携)