问题标签 [memory-visibility]

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 投票
2 回答
69 浏览

java - 主线程随机没有到达终点(尝试对并发线程中的自然数求和)

我有下面的代码来找到从 1 到 5000 的自然数之和。这是一个练习并发的简单练习。

有时,当我运行代码时,最后 3System.out.println()个不显示。如果我在 中添加一个声明while(threadNb[0] > 0),就像另一个一样System.out.println(),我的问题就不会再发生了。

谁能解释我这种行为?

提前感谢您的帮助

0 投票
1 回答
585 浏览

java - volatile 引用真的保证对象的内部状态对其他线程可见吗?

在阅读“Java Concurrency in Practice”时,我遇到了以下问题 -

为了安全地发布对象,对象的引用和对象的状态必须同时对其他线程可见。正确构造的对象可以通过以下方式安全地发布:

  • 从静态初始化器初始化对象引用;
  • 将对它的引用存储到 volatile 字段或 AtomicReference 中;
  • 将对它的引用存储到正确构造的对象的最终字段中;或者
  • 将对它的引用存储到由锁正确保护的字段中。

我的问题是——第二点是真的吗?即我可以通过将对象的引用存储在易失性引用中来使其他线程可以看到对象的状态吗?如果不是,我是否错误地阅读了上述几点?

0 投票
2 回答
1560 浏览

java - 原子变量是否保证内存可见性?

关于内存可见性的小问题。

代码示例 1:

此代码在多线程环境中容易出现错误,首先是因为“if-then-act”不是原子的,其次是因为潜在的内存可见性问题,例如 threadA 将字段设置为 true,但 threadB后来希望读取该字段的值可能看不到,但仍然看到该值是假的。

最简单的解决方案是使用 synchronized 关键字,如 CodeSample2。

代码示例2:

现在,如果我希望使用原子变量,例如 AtomicBoolean(问题适用于所有原子变量),该怎么办?

代码示例 3:

除了更好的性能考虑之外,我们可以看到现在我们已经使用 AtomicBoolean 实现了与CodeSample1中的“if-then-act”类似的逻辑。代码在逻辑上做什么并不重要,我的问题是,如果 2 个线程几乎同时调用CodeSample3中的 lock() 方法会怎样,而很明显,现在对该字段的任何写入操作都将以原子方式完成,使用 AtomicBoolean 是否也保证了内存可见性?

对不起,长篇大论,只是想确保我尽可能清楚地表达出来,谢谢大家...

0 投票
1 回答
238 浏览

java - java匿名内部类实现Runnable和共享外部类对象是否线程安全?

如代码所示,创建线程共享主线程状态对象。我认为它不是线程安全的,由于cpu缓存,主线程和创建线程将状态对象加载到自己的缓存中,当创建线程调用'setStatus'时方法它只更新它的缓存数据,主线程现在看不到更新的数据。所以需要同步。我理解正确吗?

0 投票
0 回答
30 浏览

java - 相对于新线程而言,Thread.start() 线程之前的操作是否安全?

Thread.start()与新线程的启动相关的变量可见性和/或指令顺序是否有任何保证?

具体来说,在下面的简约示例中,我是否正确假设var应该是volatile为了使输出具有确定性并始终打印“var = 10”?

注意:我的问题仅适用于 Java 5 中引入的“新”Java 内存模型

0 投票
0 回答
144 浏览

java - Spring 和 Java 可见性

最近我们的系统一直在经历各种与 Spring 相关的“巫毒”。它通常是这样的:

各种单例 bean 具有(ctor)自动装配属性,它们基于这些属性实例化一些内部数据结构。在某些时候,我们开始看到内部状态未初始化的现象,尽管事实上构建了 bean 并将其分发给应用程序。它当然是以非确定性的方式发生的。

一个典型的 bean 看起来像这样:

在某些时候,我偶然发现了这篇文章这个 SO 答案以及Brian Goetz 的这篇文章。我正遭受这个问题的困扰。阅读完这些后,我有两个后续问题:

山羊写道:

因此,您可以拥有一个指向数组的最终指针,而不必担心其他线程会看到数组引用的正确值,但数组内容的值不正确

问题 1

这个陈述是及物的吗?这意味着这不仅适用于最终变量引用的对象,还适用于它们引用的对象等(覆盖整个“可达”对象树)?

另外,如果我有以下情况怎么办:

Foo 看起来像这样:

问题2

这个“技巧”是否确保了“东西”的可见性?

换句话说 - 我有一个在其 ctor 之外初始化的类(不能有最终成员)。但我仍然想确保能见度。因此,我将状态包装在一个对象中,该对象将其分配给其 ctor 内的最终变量。

0 投票
1 回答
121 浏览

java - 如果线程 B 希望看到线程 A 所做的更改,是否只能对 volatile 变量进行最后更改,而不是全部更改?

我看过这个答案,它说明了如何:

在新的内存模型下,当线程 A 写入 volatile 变量 V,而线程 B 从 V 中读取时,在写入 V 时对 A 可见的任何变量值现在都保证对 B 可见。

因此,举个例子:

尽管(only )value的非易失性,是否保证对 (从 -1 到 1) 的更改对线程 b 可见?valueread

如果是这样,考虑到为了对另一个线程可见而执行的一堆更改,除了最后一个易失性之外,是否有任何目的更改任何变量?

0 投票
3 回答
1304 浏览

java - Java ConcurrentHashMap.computeIfPresent 值修改可见性

假设我有一个以集合为值的并发映射:

我更新值如下:

我知道computeIfPresent整个方法调用是原子执行的。但是,考虑到这个映射是由多个线程同时访问的,我有点担心对底层集合所做的修改的数据可见性。在这种情况下,调用后会在列表中看到值 5map.get

我的问题是,如果在方法调用map.get中执行更改,则调用时将更改为在其他线程中可见的列表。computeIfPresent

请注意,如果我在执行更新操作之前参考列表,我知道对列表的更改将不可见。如果我map.get在更新操作后引用列表(通过调用),我不确定对列表的更改是否可见。

我不确定如何解释文档,但在我看来,happens-before 关系将保证在这种特殊情况下对基础集合的更改的可见性

更正式地说,给定键的更新操作与报告更新值的键的任何(非空)检索具有发生前的关系

0 投票
0 回答
49 浏览

java - 一次填充单例并从java中的所有线程访问数据

我现在在手机上,所以我这里没有代码。但这很简单。

我有一个静态类在 Web 应用程序中作为单例工作。该类在应用程序启动时被调用(当我用来填充我的单例时,在数据库调用后传递一个参数)。问题是,当我从不同的静态类(在不同的线程上)再次调用该类时,我的数据不存在。但是如果我使用我用来填充的同一个类,数据就在那里。我该怎么做才能从所有类/线程访问我的单例并获取数据?

更新 大家好,我解决了。问题是我的系统有两个独立的包(由一个休息服务链接)。这两个包调用了我的单身人士,所以我得到了不同的线程。解决方案是创建一个方法并通过同一个包获取我的单例。

0 投票
0 回答
239 浏览

go - 如何在 Go 中演示内存可见性问题?

我正在做一个关于Go Memory Model的演讲。内存模型表明,如果在一个 goroutine 中的写入和另一个 goroutine 中的读取之间没有发生之前的关系,就无法保证读者会观察到变化。

为了对观众产生更大的影响,而不是仅仅告诉他们如果不同步就会发生坏事,我想向他们展示。

当我在我的机器(2017 MacBook Pro with 3.5GHz dual-core Intel Core i7)上运行以下代码时,它成功退出。

我能做些什么来证明内存可见性问题吗?

例如,我可以对以下值进行任何特定更改以证明该问题:

  • 使用不同的编译器设置
  • 使用旧版本的 Go
  • 在不同的操作系统上运行
  • 在不同的硬件上运行(例如 ARM 或具有多个 NUMA 节点的机器)。

例如,在 Java 中,标志-server-client影响 JVM 进行的优化并导致出现可见性问题。

我知道答案可能是否定的,并且编写规范可能是为了给未来的维护者更多的优化灵活性。我知道我可以通过设置使代码永远不会退出,GOMAXPROCS=1但这并不能证明可见性问题。