问题标签 [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 回答
346 浏览

java - 如何使用双重检查锁定使此代码线程安全?

单线程版本:

现在我正在尝试制作一个带有双重检查锁定的线程安全版本:

这个对吗?

0 投票
2 回答
135 浏览

java - 对单例进行双重检查似乎可以正常工作而不会被破坏,为什么以及如何?

我已经读过单例的双重检查机制是失败的,因为 JVM 后面的一些内存模型使得即使构造函数没有完全执行,引用读取也不为空。

我尝试通过在下面的代码中的构造函数中进行操作来测试相同的内容,但即便如此它似乎工作正常。

}

我得到的结果是 10 10 10 10 10 10

我期望很少有线程读取值 0 而不是 10,但每次该值被正确读取为 10 ,所以它在 J​​ava SE-1.6 中解决了问题,因为我使用的是相同的?

0 投票
2 回答
660 浏览

sql - 在 SQL 中使用双重检查锁定死锁

我的 SQL 语句遇到死锁,我想在其中选择一个 ID(如果存在),否则插入然后选择它。正如这里所建议的,我正在使用双重检查锁定来防止锁定开销。

显然我这样做是为了支持并发插入,并且我正在运行多个线程。我的 SQL 知识非常低,所以我可能错过了一些关于锁定的基本知识?这是我的程序:

更新

这可以通过在事务内的 Select 语句上使用适当的锁(XLOCK、ROWLOCK、HOLDLOCK)来解决。

下面是使用 MERGE 语句编写的过程,不需要事务:

0 投票
1 回答
474 浏览

c# - 带有双重检查锁定的单例 - 错误“正在被另一个进程使用”

我已经在网上阅读了很多关于 Singleton 的文章,但是大多数文章只展示了创建具有正确锁定的简单对象以确保线程安全而没有竞争条件。

简单到可以演示,我在里面放了一个文件记录方法。它适用于 10-20 个并发线程,但是当我尝试 100 个线程时,它将失败,给出“该进程无法访问该文件,因为它正被另一个进程使用”。

为了从客户端调用它,我设置了一个简单的 Windows 窗体和线程来通过调用生成多线程:

好吧,我知道它失败的原因是因为前一个 _instance 被传递到下一个线程,其中内部文件操作未完成导致错误。但不知道如何解决这个问题。

我也试过这个..如果我用SqlConnection替换文件IO写入,我会得到“连接没有关闭。连接的当前状态是打开的”而不是“进程无法访问文件,因为它正在被另一个进程使用”。同样的想法。当然,您将使用连接池而不是单例,但这只是出于我自己的好奇心。

我阅读了“C# in Depth”文章并尝试了不同的方法但没有奏效。即使使用 .NET 4.0 Lazy 也不能解决问题。唯一成功的解决方法是通过在 _instance 上使用 [ThreadStatic] 属性来打破单例规则,并且不再需要 DCL。但是随后它将类变成了具有延迟初始化的多线程类,不再是真正的 Singleton。

所以,我想知道.. Singleton 如何解决这个问题?

0 投票
2 回答
1325 浏览

java - Future 的 ConcurrentHashMap 和双重检查锁定

鉴于:

  • 一个惰性初始化的单例类,使用双重检查锁定模式实现,所有相关volatile内容synchronized都在getInstance. ExecutorService这个单例通过,启动异步操作
  • 有七种类型的任务,每一种都由一个唯一的键标识,
  • 启动任务时,它会存储在基于 的缓存中ConcurrentHashMap
  • 当客户端请求任务时,如果缓存中的任务完成,则启动并缓存新的任务;如果它正在运行,则从缓存中检索任务并将其传递给客户端。

这是代码的摘录:

我有一个大问题,还有一个小问题:

  1. 我是否需要在我的getTask方法中执行双重检查锁定控制?我知道ConcurrentHashMap读操作是线程安全的,所以 myget(key)是线程安全的,可能不需要双重检查锁定(但对此非常不确定……)。但是isDone()Future的方法呢?
  2. 你如何在一个synchronized块中选择正确的锁对象?我知道它一定不是null,所以我首先在方法中使用TaskLauncher.class对象,getInstance()然后tasksCache在方法中使用已经初始化的getTask(String key)。事实上,这个选择有什么重要性吗?
0 投票
1 回答
377 浏览

c# - Java中的双重检查锁定是否需要`volatile`而不是C#?

Java 程序员都知道,为了使双重检查锁定能够正常工作,必须声明变量volatile,并且同步对象的初始化是不够的。

这种认识可能主要是因为volatile关键字的语义在 1.5 中被更改为包含“发生在之前”关系,至少部分是为了使双重检查锁定安全;据我了解,“之前发生”关系意味着写入 volatile 变量会导致线程中的所有缓存变量都写入主内存,并且在从 volatile 变量中读取之后,所有缓存的变量都被认为是陈旧的,并且必须是从主存储器重新读取,以便在写入 volatile 变量之前写入的所有内容都保证“发生在”以后从该变量读取之前。

Stack Overflow似乎认为,对于 C#,volatile双重检查锁定是不必要的(尽管注意到这可能特定于某些 CPU 或 Microsoft 的实现),同时还认为 Javasynchronized语句的语义与C# 的完全一样lock声明,这表明在 Java 中确定的相同问题也将存在于 C# 中,除非在两种语言之间的双重检查锁定的语义上存在其他一些主要差异。

那么......哪个是正确的?C# 中的双重检查锁定实际上比 Java 中的危险小吗?如果是这样,有什么不同的语言语义可以做到这一点?

如果没有,具体会出现什么问题volatile?C#中的语义是否volatile像 Java 一样建立了“先发生”关系,因此双重检查锁定在 C# 中与volatile自 1.5 以来在 Java 中一样安全?

0 投票
2 回答
93 浏览

java - 使用 HashMap 进行双重映射

我们一直在编写一段代码来获取单例。我们尝试获取它们,如果该类存在于我们的集合中,我们将返回它,否则我们创建它并将其存储在我们的集合中。我们使用双重检查锁定来确保我们不会在每个 get 操作上同步。

然而,根据很多文章双重检查锁定被打破。但是我不知道这里是否是这种情况,因为地图已经初始化并且对包含进行了检查。你们有什么感想?无论如何要在这里进行双重检查锁定工作吗?

谢谢

0 投票
1 回答
33 浏览

performance - 性能测试:带和不带双重检查锁定的单例类

我有两个单例类的实现

和:

我想根据所花费的时间参数化我的发现,我所做的是:

我得到的结果是:

S1 4636498 所用时间 S2 5127865 所用时间

第一个问题这是正确的方法吗?其次,即使我getinstances在这两个中注释该方法call(),我也会得到两个相同块的不同执行时间:

S1 所用时间 1506640 S2 2156172 所用时间

0 投票
3 回答
4208 浏览

java - 以线程安全的方式延迟初始化 Java 映射

我需要延迟初始化地图及其内容。到目前为止,我有以下代码:

这显然不是线程安全的,就好像一个线程在someMap为 null 时出现,继续将字段初始化为new HashMap,当它仍在地图中加载数据时,另一个线程getValue在可能存在的情况下执行并且不获取数据.

如何确保在第一次getValue调用发生时数据仅在地图中加载一次。

请注意,key在所有初始化之后,地图中可能不存在 。此外,在所有初始化之后,地图可能只是空的。

0 投票
1 回答
182 浏览

java - JAVA中的双重检查锁定

在 Wikipedia 中阅读DCL 时,我想知道 DCL 中的问题和建议的解决方案,或者换句话说,为什么volatile需要关键字?简而言之,问题是:在某些情况下,使用 DCL 可能会导致线程使用部分构造的对象。建议的解决方案(对于 JAVA 5+):

现在,我的问题是为什么不放弃volatilefrom 助手?如果我错了,请纠正我,但如果你只是打破这一行:helper = result = new Helper();到:

在这种情况下,helper在对象完成之前永远不会获得引用。不是这样吗?表现如何volatile更好?

编辑:假设这段代码:

如果初始化后的下一行不能保证一个完全初始化的对象,我不能调用它的方法。我可以吗?