问题标签 [memory-model]
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.
synchronization - 线程同步:如何保证写入的可见性
已经有很多关于软件和硬件内存模型、内存栅栏、存储/加载重新排序等的信息。然而,这一切似乎都集中在保证读写共享内存的相对顺序上。
这样的系统将线程的写入完全延迟很长时间是否是合法行为?
例如,考虑一个线程对内存中的数据结构进行一些更新,然后引发一个应该通知其他线程更新的标志:
根据我读过的大多数内存模型,内存屏障保证任何其他线程都无法将 dataWritten 视为 true,同时仍读取过时的值 1、2 或 3,即它使这些写入原子。
但是我能确定这些写的东西会被看到吗?只要标志的写入时间不早于值,在内存模型下无限期延迟写入是否合法?
用数据库术语来说,内存模型可以用来推理持久性(除了原子性和一致性,这可以通过使用上面示例中的内存围栏和标志来保证)?
更新: 关于可见性及时性的 volatile 详细语义解决了 Java 内存模型上下文中的同一主题,以及内存模型排序和可见性?对于 C++11。该讨论是否也适用于硬件内存模型,即 CPU ISA 是否只为正确的可见性序列提供硬保证,但为延迟可见性提供“软”保证?
c++ - 出版安全、宽松的记忆模型和 memcpy
我正在尝试在有关发布安全的部分中关注这篇文章。我的情况与文章中的简单示例没有什么不同,但“发布”的数据不是单个值,而是一个struct
. 发布者将单独编写每个字段,因此通过将每个写入与存储一起包装memory_order_release
我应该没问题。
消费者将首先检查memory_order_acquire
数据是否准备就绪。然后,我很想使用 amemcpy
将整个发布的内容复制struct
到其他地方(因为它更适合其他预先存在的代码),但这似乎不安全,因为我无法指定内存模型。这只是偏执狂还是会是一个严重的问题?
接受特定于 amd64/x86 的建议。
java - 为什么 java.lang.Class.newInstance0() 在 java 内存模型下不是严格正确的?
java.lang.Class.newInstance0()
我在 JDK 1.7 Update 7 中遇到了以下注释:
注意:以下代码在当前 Java 内存模型下可能并不完全正确。
有人可以解释为什么吗?
c++ - 为什么 memory_order 作为 std::atomic 函数的运行时参数给出
std::atomic
store
和load
接受参数等std::memory_order
函数。参数可以在运行时确定,就像任何其他函数参数一样。但是,实际值可能会影响编译期间代码的优化。考虑以下:
如果memOrd
碰巧memory_order_relaxed
,第二家商店可以安全地移到第一家之前。这将在加载value
和使用它之间增加一些额外的工作,这可能会防止其他需要的停顿。但是,如果memOrd
是memory_order_seq_cst
,则不应允许切换存储,因为某些其他线程可能会依赖ai1
已设置为value
ifai2
设置为 1。
我想知道为什么将内存顺序定义为运行时参数而不是编译时间。在决定最佳内存操作语义之前,是否有任何理由让某人在运行时检查环境?
java - JLS 是否允许此指令重新排序?
根据 Java 语言规范(示例 17.4-1),以下代码段(从 开始A == B == 0
)...
... 可能导致r2 == 2
和r1 == 1
。这是因为执行的结果B = 1;
不取决于是否r2 = A
已经执行,因此JVM可以自由地交换这两条指令的执行顺序。换句话说,规范允许以下交织:
这显然导致r2 == 1
和r1 == 1
。
我的问题:
假设我们稍微调整一下这个例子:
whereobj
是线程之间共享的引用。
r2 = A
重新排序是否B = 1
仍然允许?
JLS 说……
但是,允许编译器对任一线程中的指令重新排序,只要这不会影响该线程的单独执行。
...这表明指令仍可能被交换。另一方面,以下声明
监视器上的解锁发生在该监视器上的每个后续锁定之前。
表明在某些调度下,我们可能在两个线程中的语句之间存在发生前的关系,这可能不允许指令重新排序。
c# - c# 内存模型、锁定和同步
c# 内存模型是否保证持有锁的线程可以看到所有执行的更新,而任何其他线程先前持有相同的锁?
我一直在阅读 c# 规范,但似乎无法找到这方面的细节。
c - 从内核空间访问数据段
我希望能够知道属于进程的页表中的哪些页面用作数据段。我正在为 amd64 使用 Linux 内核 v 3.2
这是我以前做过但没有用的:
使用
task->mm->start_data
(任务是目标进程的task_struct)访问数据段。搜索
task->mm->mmap
(链表)并将每个vm_area_struct
(vm_start
) 的起始地址与task->mm->start_data
. 这里我假设数据段的开头与页面的开头对齐。
所有这些都应该在内核模块中完成。
谢谢。
c++ - 并发写入同一缓存行中的不同位置
假设我有一个 C++11 应用程序,其中两个线程使用指向原始类型的简单指针写入不同但附近的内存位置。我能否确定这两个写入最终都会在内存中结束(可能在两者都达到 a 之后boost::barrier
),或者是否存在两个 CPU 内核拥有自己的包含该数据的缓存行的风险,并且第二个内核将其修改刷新到 RAM会覆盖并撤消第一次写入所做的修改吗?
我希望缓存一致性能够在所有情况下以及在所有符合 C++11 内存模型的设置上为我解决这个问题,但我想确定一下。
c++ - C++ memory_order_consume、kill_dependency、dependency-ordered-before、synchronizes-with
我正在阅读Anthony Williams 的C++ Concurrency in Action。目前我在他描述memory_order_consume的地方。
在那个块之后有:
现在我已经介绍了内存排序的基础知识,是时候看看更复杂的部分了
这让我有点害怕,因为我不完全理解几件事:
之前的依赖排序与同步有什么不同?他们都创造了“事前发生”的关系。确切的区别是什么?
我对以下示例感到困惑:
kill_dependency 到底是做什么的?它杀死了哪个依赖?哪些实体之间?以及编译器如何利用这些知识?
memory_order_consume 的所有出现都可以安全地替换为 memory_order_acquire 吗?即它在所有意义上都更严格吗?
在代码清单 5.9 中,我可以安全地替换吗
和
? 即获取和释放可以用来同步访问非原子数据吗?
他通过一些小隔间里的男人的例子来描述放松、获得和释放。seq_cst和consume有没有类似的简单描述?