问题标签 [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.
concurrency - 内存屏障是否仅在 SMP 中有意义?
我理解为什么需要内存屏障,但在单处理器的情况下我不明白。
即使使用 UP,我也必须处理障碍吗?每个文档都使用 SMP 而不是 UP 来解释它们。
在下面的代码中,有没有可能r2 == 0
在 a 点?
.net - MemoryBarriers 和并行扩展
使用并行扩展时是否需要关注 MemoryBarriers?
编辑 - 详细说明原始问题是开放式的:(@xanatos 的答案是我正在寻找的答案)
举一个具体的例子:假设我使用 Parallel.ForEach 并且每次迭代都设置类中属性的值(每次迭代都设置它自己的特定属性,没有两次迭代设置相同属性的值)。在调用 Parallel.ForEach 的同一线程上,我访问从 Parallel.ForEach 设置的属性。
c# - 并发互锁和读取是否需要内存屏障或锁定?
这是一个简单的问题,但是在阅读了为什么我需要内存屏障?我对此很困惑。
在下面的示例中,假设不同的线程重复调用 Increment 和 Counter:
对不起,如果我误解了为什么我需要内存屏障?但似乎它暗示上面的类在读取_counter的值时可能没有提供新鲜度保证。重复访问 Counter 属性的线程是否会永远停留在 Counter 的旧值上(因为它被缓存在寄存器中)?
在必要之前是内存屏障还是锁return _counter;
?
java - 内存屏障有没有很好的介绍?
我正在寻找关于内存障碍和 Java 代码中常见陷阱的良好在线介绍:
- 使用
synchronized
太频繁或不够频繁 - 何时使用
volatile
和final
- 双重检查锁定
- 等等
我对显示行为和/或示例如何解决常见问题的代码特别感兴趣(例如创建多个线程可以访问的映射以及延迟添加值的位置)。
c - 函数调用是现代平台的有效内存屏障吗?
在我查看的代码库中,我发现了以下成语。
“等一下”,我对作者,我团队的一位资深成员说,“这里没有内存屏障!你不保证global.data
会从缓存刷新到主内存。如果线程A和线程B会运行两个不同的处理器——这个方案可能会失败”。
高级程序员咧嘴一笑,慢慢解释,好像在解释他五岁的男孩如何系鞋带:“听着小男孩,我们在这里看到了很多线程相关的错误,在高负载测试中,在真实客户端中”,他停下来抓挠他长长的胡须,“但我们从来没有遇到过这个成语的错误”。
“可是,书上说……”
“安静!”他迅速让我安静下来,“也许理论上,不能保证,但实际上,你使用函数调用的事实实际上是一个内存屏障。编译器不会重新排序指令global.data = data
,因为它不知道是否任何在函数调用中使用它的人,x86 架构将确保在线程 B 从管道中读取命令时,其他 CPU 将看到这条全局数据。请放心,我们有很多现实世界的问题要担心。我们不需要在虚假的理论问题上投入额外的精力。
“放心,我的孩子,到时候你会明白将真正的问题与我需要获得博士学位的非问题区分开来。”
他是对的吗?这在实践中真的不是问题吗(比如 x86、x64 和 ARM)?
这与我学到的一切背道而驰,但他确实留着长胡子和非常聪明的外表!
如果你能告诉我一段代码证明他错了,加分!
multithreading - _ReadWriteBarrier 是否确保跨线程动态分配的缓冲区的可见性?
我正在使用 Visual C++ 和 Windows 7 和 XP。我在一个程序中有两个线程,在创建两个线程之后,一个线程动态创建一个缓冲区并将其地址分配给一个全局指针,然后将数据写入该缓冲区。调用 _ReadWriteBarrier 会保证该数据对第二个线程的可见性吗?
例如:
我相信从保证地址可见性的文档中,就像一个全局变量一样。但它是否也保证了创建的缓冲区本身的可见性?甚至有必要吗?_ReadWriteBarrier
buff
buff
main
c# - c# struct数组的并发
给定一个结构数组:
以及一个线程任务池,它基于单个元素最多可以由两个线程同时写入,一个用于双字段中的每一个(有效地按主题进行上游排队)来写入这些元素。
并且可以在 64 位上原子地写入 double 的知识。(编辑这个误说原来是32位)
我需要使用数组中的所有值定期执行计算,并且我希望它们在计算期间保持一致。
所以我可以使用以下方法对数组进行快照:
现在我的问题是关于同步的细节。如果我让成员变得易变,我认为这根本不会帮助克隆,因为读/写获取/释放不在数组级别。
现在我可以有一个数组锁,但这会在最频繁的向数组中写入数据的过程中增加很多争用。所以不太理想。
或者我可以有一个每行锁,但这将是一个真正的痛苦,因为它们都需要在克隆之前被获取,同时我已经得到了所有的写入备份。
现在,如果快照没有最新的值,如果它只是微秒等问题,这并不重要,所以我想我可能只是没有锁就可以逃脱。我唯一担心的是,是否可能存在持续一段时间没有缓存写回的情况。这是我应该担心的事情吗?编写者在 TPL 数据流中,唯一的逻辑是在结构中设置两个字段。我真的不知道函数范围如何或是否倾向于与缓存回写相关。
想法/建议?
编辑:如果我对结构中的变量使用互锁写入怎么办?
edit2:写入量远高于读取量。还有两个单独和并发的服务写入 Nos 和 Last 字段。所以它们可以同时被写入。这会导致原子性参考对象方法出现问题。
编辑3:更多细节。假设数组包含 30-1000 个元素,并且每个元素可以每秒更新多次。
.net - 代码应该对 CPU 内存模型做出哪些假设,以及如何记录这些假设?
根据我的阅读,英特尔处理器架构强制执行比 .net 实现所需提供的更强大的内存模型。代码在多大程度上利用英特尔处理器做出的保证是合适的,或者代码应该在多大程度上添加英特尔实现不需要的内存屏障,以防代码迁移到一个较弱的平台记忆模型?定义一个带有方法的静态类是否合适,例如“如果使用弱内存模型,则执行内存屏障”,并要求代码酌情与该库的“强模型”或“弱模型”版本链接?或者,是否可以在程序启动时使用反射来生成这样一个静态类,这样 JIT 编译器可以在使用强模型时,“
如果我有我的 druthers,.net 将提供MemoryLock
具有一些半锁操作的类的变体,这将要求所有持有半锁的线程都必须遵守该半锁的内存模型。在具有非常强大的内存模型的系统中,半锁不会做任何事情。在内存模型非常弱的系统中,任何希望进入已经有另一个线程的半锁的线程都必须等到第一个线程退出,或者它可以被 CPU 或内核调度(基于根据半锁指定的模型)第一个线程正在使用。请注意,与普通锁不同,aMemoryLock
永远不会死锁,因为任何冲突的锁定要求的组合都可以通过调度所有线程在同一个 CPU 上运行来解决,并且系统可以释放MemoryLock
由死掉的线程持有的任何线程(因为这样做的目的MemoryLock
是保护资源不被访问以违反内存模型的方式,死线程当然不能进行此类访问)。
当然,从 .net 4.0 开始就不存在这样的东西了;鉴于此,处理确实存在的情况的最佳方法是什么?将专为更强的内存模型设计的代码迁移到具有更弱模型的系统,在没有一些方法来强制执行更强的模型的情况下,将是灾难的根源,但是添加大量Lock
或MemoryBarrier
对于代码的原始目标平台而言,不必要的调用似乎不是很吸引人。我所知道的强制使用强内存模型的代码的唯一方法是让每个线程设置其 CPU 亲和性。如果有一种方法可以设置一个进程选项,这样 .net 一次只能使用一个内核,那可能会很有用(特别是如果它意味着 JIT 可以用更快的非总线锁定等价物代替总线锁定互锁操作) ,但我知道设置 CPU 亲和性的唯一方法是限制程序将特定选定的 CPU 用于其所有线程,即使该 CPU 被其他应用程序负载过重并且其他一些 CPU 处于空闲状态。
附录
考虑以下代码:
据我了解,即使没有内存屏障,在英特尔处理器上运行的代码也能保证写入不会被重新排序;因此,在线程 2 中,被读取的人要么是“Smiley”、“George”,要么是“Simpson”、“Bart”。然而,.net 内存模型比这更弱,.net 程序可能会发现自己运行在线程 2 可能会看到不完整对象的处理器上(因为写入SharedPerson
可能发生在写入之前newPerson.FirstName
)。在 at 添加内存屏障MaybeMemoryBarrier1
可以避免这种危险,但无论是否实际需要内存屏障,都会有性能成本。
我认为最低要求的 .net 内存模型不会那么弱,以至于在保证线程 2在读取自身之前MaybeMemoryBarrier2
永远不会访问所引用的对象的情况下需要(如上面代码中的情况,因为新实例在存储到 ) 之前不会暴露给任何外部代码。另一方面,假设情况略有变化,因此创建了一条记录,然后将其放入队列中(假设队列本身所有必要的锁和内存屏障);之后,处理器会:SharedPerson
SharedPerson
SharedPerson
Thread 2
JobInfo
Thread 1
如果线程 1 有内存屏障,但线程 2 没有,是否可以保证当线程 2 看到JobInfo
它创建的记录出现在 中时CurrentJob
,它会正确读取其StartTime
字段(并且不会看到缓存或部分缓存的值从Thread 2
操纵那个物体的时候开始?
c# - 系统正常运行时间和内存屏障
我需要一种可靠的方法来获得系统正常运行时间,并最终使用如下方法。添加了一些评论以帮助人们阅读它。我不能使用 Task,因为它必须在 .NET 3.5 应用程序上运行。
我正在努力的部分是应该Thread.MemoryBarrier()
放在哪里?我在读取值之前放置它,但是当前线程或不同的线程可能已经写入它。以上看起来正确吗?
编辑,根据丹尼尔回答
这就是我最终实现的,谢谢你们的洞察力。
编辑 2
根据 Bob 的评论更新。