问题标签 [double-checked-locking]

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 投票
1 回答
633 浏览

java - Java中没有同步的线程安全单例?

我有一个多线程应用程序和一个单例类:

当然,这在一般的多线程场景中是行不通的。但请考虑以下情况:

  • 一开始只有一个线程
  • 这个线程getInstance()第一次调用,以便初始化 mc。
  • 之后,所有其他线程都由第一个线程启动。

我的假设:

这应该起作用,因为mc字段的初始化和对象的构造发生在启动其他线程的所有后续Thread.start()调用之前。并且Thread.start()线程发生在该线程的所有其他操作之前。它遵循mc在所有其他线程中的所有操作之前发生的初始化,以便getInstance()为所有线程返回正确的值。

这个假设正确吗?为什么/为什么不?

0 投票
1 回答
261 浏览

java - 双重检查锁定是否仅在惰性初始化场景中被破坏?

我读了这篇文章:“双重检查锁定被破坏”声明,它说

双重检查锁定被广泛引用并用作在多线程环境中实现延迟初始化的有效方法。

不幸的是,当用 Java 实现时,它不能以独立于平台的方式可靠地工作......

而这篇文章:双重检查锁定:聪明,但坏了,它说:

DCL 习惯用法旨在支持延迟初始化...

我的问题是:

  1. 只有在尝试进行延迟初始化时才会破坏双重检查锁定?

  2. 它是否也在像下面的代码这样的场景中被破坏(所有东西都已经初始化)?

代码:

0 投票
1 回答
649 浏览

java - Why does ConcurrentHashMap work in Double Checked Locking

In the book "Java Concurrency in Practice" is mentioned that the following code is not threadsafe:

It is not thread safe because because: - one thread can create new instance of Resource - another thread at the same time in the "if" condition can get not empty reference but the object of Resource will not be completly initialized

In this question is similar code. Resources are stored in concurentHashMap and people say that it is threadSafe. Something like this:

Why does storing the values in ConcurrentHashMap make the code threadSafe? I think that it is still possible that the ComplexObject won't be completely initialized and this "partial object" will be saved in the map. And other threads will be reading partial not fully initialized objects.

I think I know what is "happens-before", I've analyzed code in JDK 8.0_31 and I still don't know the answer.

I am aware of the functions like computeIfAbsent, putIfAbsent. I know that this code can be written differently. I just wan't know details which make this code threadsafe.

0 投票
1 回答
166 浏览

java - 为什么要仔细检查单例实例化

链接中,我找到了如下的单例实例化:

我没有得到单次检查的意义,即 (1) 。它在这里有什么用,单线程将检查同步块内的实例,那么使用第一次检查有什么意义呢?

0 投票
5 回答
8758 浏览

java - 没有 volatile 的双重检查锁定

我读了这个关于如何进行双重检查锁定的问题:

我的目标是在没有 volatile 属性的情况下延迟加载字段(不是单例)。初始化后字段对象永远不会改变。

经过一些测试我的最终方法:

由于不需要 volatile,好处可能是更快的访问时间,同时仍然保持可重用 Publisher 类的简单性。


我使用 jcstress 对此进行了测试。SafeDCLFinal 按预期工作,而 UnsafeDCLFinal 不一致(如预期)。在这一点上,我 99% 确定它有效,但请证明我错了。编译mvn clean install -pl tests-custom -am并运行java -XX:-UseCompressedOops -jar tests-custom/target/jcstress.jar -t DCLFinal. 下面的测试代码(主要是修改过的单例测试类):

使用 java 8 测试,但至少应该适用于 java 6+。查看文档


但我想知道这是否可行:

甚至可能:

或者:

我相信这会基于这个 oracle doc工作:

final 字段的使用模型很简单:在对象的构造函数中设置对象的 final 字段;并且不要在对象的构造函数完成之前在另一个线程可以看到它的地方写入对正在构造的对象的引用。如果遵循这一点,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本。它还将看到至少与最终字段一样最新的最终字段引用的任何对象或数组的版本。

0 投票
1 回答
456 浏览

java - 这是双重检查单例的正确使用吗?

我基本上是在为 HelperWrapper 的用户寻找一种缓存机制。这是双重检查单例的正确使用吗?

我知道这不会阻止某人实例化他们自己的 Helper 对象,但这不是目标。

附加信息:

  • 我无法修改 Helper 类以使构造函数私有。我也不想。
  • 要求规定不应急切地实例化助手
0 投票
4 回答
432 浏览

c++ - 我的双重检查锁定模式实现正确吗?

Meyers 的《Effective Modern C++ 》一书中的一个例子,第 16 条。

在缓存计算成本高的 int 的类中,您可能会尝试使用一对 std::atomic 可变量而不是互斥锁:

这会起作用,但有时它会比应有的工作更难。考虑:一个线程调用 Widget::magicValue,将 cacheValid 视为 false,执行两个昂贵的计算,并将它们的总和分配给 cachedValud。此时,第二个线程调用 Widget::magicValue,也将 cacheValid 视为 false,因此执行与第一个线程刚刚完成的相同的昂贵计算。

然后他给出了一个互斥锁的解决方案:

但我认为解决方案不是那么有效,我考虑将互斥锁和原子结合起来组成一个双重检查锁定模式,如下所示。

因为我是多线程编程的新手,所以想了解一下:</p>

  • 我的代码对吗?
  • 它的性能更好吗?

编辑:


修复了代码。if (!cachedValue) -> if (!cacheValid)

0 投票
1 回答
716 浏览

c++ - C++11 中双重检查锁定模式 (DCLP) 的实现是否正确?

我正在阅读有关 DCLP(双重检查锁定模式)的信息,但我不确定我是否正确。当使用原子来创建锁时(如DCLP 中所述,在 C++11中修复),有两件事不清楚:

  1. 在文章的代码中:

如果我在“load()”中获取栅栏,但 tmp 不是 nullptr,我只是返回,会发生什么情况?我们不应该说明 CPU 可以在哪里“释放围栏”吗?

如果不需要释放栅栏,那我们为什么要获取和释放?有什么区别?

Surly我错过了一些基本的东西......

  1. 如果我正确理解了这篇文章,那么这也是实现 DCLP 的正确方法吗?

换句话说,我没有查看实例,而是使用原子布尔值来确保 DCLP 工作,并且第二个 tmp 内的任何内容都必须同步并运行一次。这是对的吗?

谢谢!

编辑:请注意,我不是在问实现单例的问题,而只是为了更好地理解栅栏和原子的概念以及它如何修复 DCLP。这是一个理论问题。

0 投票
1 回答
60 浏览

java - 在 Spring bean 中访问 Db 时的线程安全

我有一个由 spring rest 控制器调用的单例 spring 服务。

单例服务MyService有一些方法addRecordIfNotExistsBefore,它有以下实现:

问题是 - 正如出现的那样 - 当两个客户端同时请求相同的服务时,记录会被两次添加到数据库中。

我可以在一些简单的实现中应用双重检查习语,例如:

它是有效的解决方案,还是有其他更好的解决方案?

0 投票
2 回答
155 浏览

c++ - 仅使用 volatile 修复 DCLP

我正在阅读文章“ C++ and the Perils of Double-Checked Locking ”,它解释了 DCLP 中的问题。

文章的第二部分(链接转发)展示了如何尝试仅使用 C/C++ volatile 解决 DCLP(据我所知,这是不可能的)。在文章中,作者解释了如何做到这一点(最后一个例子是 11 号),但他们写道:

不幸的是,这一切都无助于解决第一个问题——C++ 的抽象机器是单线程的,而且 C++ 编译器可能会选择从刚才提到的源代码生成线程不安全的代码,无论如何。否则,失去优化机会会导致效率损失过大。毕竟这一切,我们回到第一方。但是等等,还有更多——更多的处理器。

这意味着(如果我理解正确的话),无论我们将如何使用 volatile,它都不会起作用,因为“ C++ 的抽象机器是单线程的,C++ 编译器可能会选择从源代码生成线程不安全的代码,例如刚才提到的

但这意味着“C++ 的抽象机器是单线程的”是什么意思?!

为什么上面所有这些挥发物的例子都不会阻止重新排序?

谢谢!