问题标签 [happens-before]
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.
java - “同步动作完全有序”是什么意思?
我正在阅读Java Concurrency in Practice,在“16.1.3 The Java Memory Model in 500 words or less”中,它说:
Java 内存模型是根据操作指定的,包括对变量的读取和写入、监视器的锁定和解锁以及启动和加入线程。JMM为程序中的所有操作定义了一个称为发生前发生的偏序。为了保证执行动作B的线程可以看到动作A的结果(无论A和B是否发生在不同的线程中),A和B之间必须存在happens-before关系。在没有happens-before排序的情况下在两个操作之间,JVM 可以随意重新排序它们。
即使动作只是部分有序的,同步动作——锁的获取和释放,以及 volatile 变量的读取和写入——都是完全有序的。这使得用“后续”锁定获取和 volatile 变量读取来描述发生之前是明智的。
关于“部分排序”,我已经找到了 this和this,但我不太明白“即使动作只是部分排序,同步操作——锁的获取和释放,以及 volatile 变量的读取和写入——都是完全有序的。” . “同步动作完全有序”是什么意思?
c++ - 结束在另一个线程中使用的对象的生命周期
标准对下面的代码有什么看法?
我特别好奇如何(或者,是否有可能)应用[basic.life]/7和[basic.life]/8说
类似地,在对象的生命周期开始之前但在对象将占用的存储空间已分配之后,或者在对象的生命周期结束之后并且在对象占用的存储空间被重用或释放之前
和
如果在对象的生命周期结束之后,在对象占用的存储空间被重用或释放之前,在原对象占用的存储位置创建一个新对象
分别,鉴于[basic.life]/11说
在本节中,“之前”和“之后”指的是“<a href="https://timsong-cpp.github.io/cppwp/n4659/intro.multithread#def:happens_before" rel="nofollow noreferrer" >发生在之前”的关系。
这是否意味着如果线程没有“看到”int
对象生命周期结束,它可以访问它,就好像它还活着一样?
起初我认为该程序存在数据竞争:
如果程序的执行包含两个潜在的并发冲突操作,则程序的执行包含数据竞争,其中至少一个不是原子的,并且两者都不会在另一个之前发生,除了下面描述的信号处理程序的特殊情况。任何此类数据竞争都会导致未定义的行为。
但是,没有相互冲突的动作。根据“冲突”的定义:
如果其中一个修改内存位置而另一个读取或修改相同的内存位置,则两个表达式求值会发生冲突。
以及“内存位置”的定义:
内存位置要么是标量类型的对象,要么是所有具有非零宽度的相邻位域的最大序列。
reads through*pi
与 store through 不冲突*pf
,因为这些左值表示不同的对象,因此表示不同的内存位置。
我觉得程序必须有UB,但看不到在哪里。
c++ - 我可以在单读/单写队列中用 volatile 替换原子吗?
让我们考虑以下使用链表实现的单读/单写队列。
现在我发现 usingvolatile int n
可以让我的 writer 运行得更快,而我不确定它是否能保证head = head->next
总是能读取到正确的值。
更新:如果在 , 之间添加原子操作tail->next
,n++
即,
a
读者永远不会访问哪个?这会保证 和 的顺序tail->next = it
吗head = head->next
?(不过,它比使用 atomic 运行得更快n
)
java - 我怎样才能在没有发生之前获得锁?
我想在没有发生之前锁定java来测试内存可见性的其他规则。而且我已经尝试过Unsafe#compareAndswapInteger
,AtomicInteger#weakCompareAndSet
他们似乎仍然保证发生之前的规则?
这是我的测试代码:
java - 持有者成员的单例模式中的线程安全
我有这个带有单例模式的示例代码:
我有一个问题:在两个线程 t1、t2 中调用的方法getCount
和setCount
哪个是线程安全的,不是吗?
java - Android ART 和 HotSpot 在非易失性变量可见性方面的行为是否不同?
我在 HotSpot 和 Android ART 上测试了以下代码,但结果不同。
在 HotSpot 上,MyThread
永远不会得到更新isRunning
,它isRunning
总是得到 = true ......但是当我在 ART 上测试它时,MyThread
可以正常获取更新isRunning
并退出循环......
据我所知,java 发生前规则,非易失性在多线程中不可见,就像下面代码在 Hotspot 上的行为一样。
它是否取决于VM实现?或者也许 Android ART 有自己的优化?
java - java在x86架构中实现之前发生,t1写入主内存?
正如预期的那样,下面程序中的读取器线程将永远运行,因为它将停止标志(非易失性)缓存在其本地处理器的缓存中。然而,一旦我在阅读器线程上取消注释 println,标志就会得到更新的标志值并且程序停止。这是怎么可能的,因为编写器线程只将标志写入其自己的本地缓存并且尚未刷新到主内存?
注意:在 MacBook Pro x86 架构的机器上运行这个程序。
java - wait() 和 notify() JMM 语义
我有一个非常特殊的问题,我找不到答案。
众所周知,在进入synchronized
块时,线程会重新读取其范围内的所有共享(非本地)变量。某些底层架构的示例:如果线程 A 在 RAM 线程 B 中更新对象的状态,则进入同步块将看到更改。退出synchronized
块时会发生类似的事情:线程将其范围内的所有内容刷新到 RAM,以便其他线程可以看到。这些是基本的 JVM 可见性保证,并且存在之前发生的规则来强制执行它。
wait()
但是,从语义上讲,代码是否使用or也执行所有这些操作并不是很清楚notify()
:毕竟它没有明确地进入或离开synchronized
块。
这些问题是:
- JVM 是否确保在
wait()
入口处对其他线程的更改可见? - JVM 是否确保在其他线程中所做的更改可见
wait()
? - 线程是否确保对其他线程的更改可见
notify()
?
c++ - 原子获取是否与互斥锁释放同步?
我有一个对象,它unordered_map
使用字符串键和变量值存储一些设置。由于我的库可能会被多个线程使用,并且读取的数量很可能会大大超过写入的数量,因此我考虑过一个写入时复制实现,其中“get”操作是无锁的,而“put”操作是关键的部分,如示例中所示:
只要获取/释放同步也会影响指向的数据而不仅仅是指针值,我有理由相信该设计是有效的。但是,我的问题如下:
- 这个工作需要锁内的原子存储吗?
- 或者原子获取是否会与作为“释放”操作的互斥锁同步?
java - Java 发生之前的关系?
考虑以下代码。
线程 A 调用run()
,然后另一个线程 B 调用test()
并且不应该有任何发生之前的关系。我知道不能保证线程 B 看到线程 A 所做的更改。但是这个程序的输出是否有可能是: