问题标签 [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.

0 投票
4 回答
378 浏览

java - Java Happens-Before 和线程安全

假设我有一个包装 HashMap 的类,如下所示:

此类通过“Thread1”初始化。但是,put、get、printMap 和其他操作只能由“Thread2”调用。

我是否正确理解这个类是线程安全的:

  1. 由于对映射的引用被声明为最终状态,所有其他线程将看到映射的初始状态(已建立之前发生)。

  2. 由于 put/get/printMap/etc 仅由 Thread2 调用,因此不需要互斥。

谢谢

0 投票
1 回答
355 浏览

java - Is happens-before relation given in case of invokeLater() or invokeAndWait?

Pretty sure it is this way - but I like to know for sure - is happens-before relation given in case of invokeLater() or invokeAndWait()?

The methods are defined in (SwingUtilities respectively) AWT.EventQueue. I guess there is synchronization involved when something is entered in the EventQueue and hence as result of the synchronization, the happens-before relation and finally the visibility is given.

But is it really that way? (and where can I find that information?)


e.g. inside some worker thread


e.g. inside some thread

0 投票
4 回答
273 浏览

java - Java - 发生在之前 - 易失性

我有以下代码

如果我increment()从多个线程调用同一个对象,我会得到以下输出(在您的机器上可能会有所不同)

查看重复的数字,我认为happens-before似乎被破坏了,因为考虑到前三个数字(2 3 2),如果线程看到 3 ,则增量已经发生,并且由于变量是易失性的,因此它的值应该是 3 或更多但是在任何线程中不能为 2。
但是,这里的打印行似乎已经重新排序,重新排序该行是否正确?我在这里想念什么?我在 JDK 7 (Eclipse) 上运行

0 投票
2 回答
254 浏览

java - Java - 监视器解锁的发生前关系

我最近阅读了http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html,它清楚地描述了 Java 内存模型的许多内在特性。一个特别的摘录引起了我的注意,即:

对我来说似乎很明显,但是在阅读了http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html和发生之前的定义后,我能找到的关于显示器解锁的所有信息都是当一个线程解锁发生的监视器- 在另一个线程再次锁定它之前(这也很有意义)。有人能解释一下 JLS 如何解释同步块中的所有操作都必须在解锁操作之前发生的明显条件吗?

进一步的评论:

基于几个回复,我想对你们一直在说的话写下进一步的评论:

  1. 在单线程中重新编码

我引用的来源中的几个“真相”:

如果new A()涉及一百个操作,然后将堆上的地址分配给a,编译器可以简单地重新排序这些操作以分配堆地址a,然后按照通常的初始化(双重检查锁定的问题)

可以改为

所以我们monitorexit用打印语句重新排序(根据 JLS 也有效)

现在,我提到的简单案例:

我认为没有理由阻止编译器先分配 x 或先分配 y。完全没有什么可以阻止它,因为无论是先分配 x 还是先分配 y,最终输出都不会改变。所以重新排序是完全可能的。

  1. 监视器.解锁

基于 print 语句被“拉入”同步块的示例,让我们尝试扭转这一点,即 startwing

我可以期望编译器这样做:

在单线程世界中似乎完全合理,但是绝对是无效的,并且针对 JLS(根据引用的来源)。如果我在 JLS 中找不到任何关于此的内容,为什么会出现这种情况?显然,关于“程序顺序”的动机现在已经无关紧要了,因为编译器可以进行重新排序,例如将语句“拉入”到同步块中。

0 投票
2 回答
95 浏览

java - Java 发生之前的说明以及如何在两个线程之间安全地来回传递对象

我想以线程安全的方式在使用任意对象的两个线程之间建立一个简单的“协议”,而不是专门针对多线程。协议应该是只有一个线程拥有对象,并且只有所有者可以读/写对象。我在这里阅读了有关发生之前 的信息,但不太确定讨论是否仅涉及单个字段或整个对象。以下两种解决方案对于“所有权协议”是否正确?

1) 使用 BlockingQueue 以便将对象通过队列传递给另一个线程。

2)“任意对象”不再那么随意了,因为我引入了一个

最初,线程 A 正在使用该对象ownedByThreadAtrue完成后,线程 Afalse写入ownedByThreadA. 线程 B 轮询与此类似的变量

我很确定(1)是一个正确的解决方案。对于(2),我不太确定。特别是对于(2),我想知道是否只有一个volatile就足以获得正确的解决方案,因为遵守了“用户协议”。

0 投票
1 回答
207 浏览

java - 通过易失性引用安全发布对象数组

以下代码是否可以安全发布?

Happens -before here 适用于每个新创建的对象还是仅适用于数组本身?

就算j里面会容纳的领域MyObject不是final

0 投票
1 回答
354 浏览

java - 没有内存屏障的乱序写入:数据竞争的唯一可能原因?

通过 Brian Goetz 实践 Java Concurrency 时,我遇到了以下行:

当一个变量被多个线程读取并被至少一个线程写入时,就会发生数据竞争,但读取和写入不是 按发生前排序的。正确同步的程序是没有数据竞争的程序;正确同步的程序表现出顺序一致性,这意味着程序中的所有操作似乎都以固定的全局顺序发生。

我的问题是,乱序是在 java 或其他编程语言中写入数据竞争条件的唯一原因吗?
更新
好的,我对数据竞争进行了更多调查,并从oracle 官方网站上发现了以下内容:

线程分析器检测在多线程进程执行期间发生的数据竞争。在以下情况下会发生数据竞争:

  • 单个进程中的两个或多个线程同时访问同一内存位置,并且
  • 至少其中一项访问是用于写入的,并且
  • 线程没有使用任何独占锁来控制它们对该内存的访问。

当这三个条件成立时,访问的顺序是不确定的,并且根据该顺序,每次运行的计算可能会给出不同的结果。一些数据竞争可能是良性的(例如,当内存访问用于忙等待时),但许多数据竞争是程序中的错误。


在这一部分中,提到:访问的顺序是不确定的
它是在谈论线程访问内存位置的顺序吗?如果是,那么同步永远不会保证线程访问代码块的顺序。那么,同步如何解决数据竞争的问题呢?

0 投票
3 回答
160 浏览

android - android中的这两个线程上的happens-before关系是如何建立的

下面是自定义 App 类和 MainActivity 类代码的示例代码示例:

和 MainActivity 类:

我正在尝试做的是在 INIT-THREAD 中将“i”的值更改为 100,并从 MAIN 线程尝试读回该值。

我期望 onResume 和 handleMessage 中“i”的值为 -100,因为它们在 MAIN 线程中执行,但 Log 打印的值实际上是 100。

在某种程度上,我试图重现每个人在常规 java 程序中都会犯的经典错误,但 android 似乎聪明地避免了它。

所以我有兴趣了解android如何实现两个线程之间的happens-before关系。

0 投票
2 回答
427 浏览

java - How does Java manage the visibility of a volatile field?

This Q is looking for specific details on how exactly Java makes a volatile field visible.

The volatile keyword in Java is used for making a variable "actively" visible to the readers of that variable right after a write operation on it is done. This is one form of happens-before relationship-- makes the results of a write exposed to whoever accessing that memory location of that variable for some use. And when used, makes the read/write operations on that variable atomic-- for long & double as well-- R/W to every other var types are atomic already.

I'm looking to find out what Java does to make a variable value visible after a write operation?

Eg.: The following code is from one of the answers on this discussion:

Reads and writes to boolean literals are atomic. if the method close() above is invoked, it is an atomic operation to set the value of close as true even if it isn't declared as volatile.

What more volatile is doing in this code is making sure that a change to this value is seen the moment it happens.

How exactly volatile is achieving this?

by giving priority to threads with operations on a volatile variable? if so - how, in thread scheduling, or by making the threads-with-read-operations go look up a flag to see whether there's a writer-thread pending? I'm aware that "A write to a volatile field happens-before every subsequent read of that same field." Is it choosing among the threads, the one(s) that have a write operation on a volatile variable before giving CPU time to threads that only read?

If this is managed in thread scheduling level (which i doubt), then running a thread with a write on a volatile field has a bigger effect than it seems.

How exactly is Java managing visibility of volatile variables?

TIA.

0 投票
2 回答
679 浏览

java - Java 内存模型中的 Happens-Before 关系

关于 JLS ch17 Threads and Locks,它说“如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作可见并在第二个动作之前排序”;我想知道:

(1) 说“之前订购”是什么意思?因为即使action_a发生在action_b之前,在某些实现中action_a也可以在action_b之后执行,对吧?

(2) 如果 action_a 发生在 action_b 之前,是否意味着 action_a 不能看到 action_b?或者 action_a 可能会看到或可能不会看到 action_b?

(3) 如果action_a没有在action_b之前发生,并且action_b在action_a之前没有发生,这是否意味着action_a可能看到或可能没有看到action_b?

(4) 不可能有任何循环的happens-before,对吧?

任何答案将不胜感激:)