问题标签 [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 投票
5 回答
4633 浏览

c# - 字典“ContainsKey”上的双重检查锁定

我的团队目前正在讨论这个问题。

有问题的代码类似于

我看过的一些帖子说这可能是一个很大的 NO NO(使用 TryGetValue 时)。然而我们团队的成员说这没关系,因为“ContainsKey”不会迭代密钥集合,而是通过 O(1) 中的哈希码检查密钥是否包含。因此,他们声称这里没有危险。

我想听听您对这个问题的诚实意见。

0 投票
5 回答
2350 浏览

c# - 为什么要使用双重检查锁定?

我一直在运行使用双重检查锁定的代码,但我仍然对为什么要使用它感到困惑。

我一开始并不知道双重检查锁定是坏的,当我学会它时,它对我来说放大了这个问题:为什么人们首先要使用它?比较和交换不是更好吗?

(我的问题同时适用于 C# 和 Java,尽管上面的代码适用于 C#。)

与原子操作相比,双重检查锁定是否具有某种内在优势?

0 投票
2 回答
2195 浏览

c# - 再次双重检查锁定和 C#

最近我一直在重构我的一些 C# 代码,我发现一些双重检查锁定实践正在发生。那时我不知道这是一种不好的做法,我真的想摆脱它。

问题是我有一个类应该被延迟初始化并经常被许多线程访问。我也不想将初始化移动到静态初始化器,因为我计划使用弱引用来防止初始化对象在内存中停留太久。但是,如果需要,我想“恢复”对象,确保以线程安全的方式发生这种情况。

我想知道是否在 C# 中使用 ReaderWriterLockSlim 并在第一次检查之前输入 UpgradeableReadLock,然后在必要时输入写锁进行初始化将是一个可接受的解决方案。这是我的想法:

我的观点是,没有其他线程应该再次尝试初始化该项目,而一旦值被初始化,许多线程应该同时读取。如果获取了写锁,可升级读锁应该阻塞所有读取器,因此在初始化对象时,行为将类似于在可升级读锁开始的地方有一个锁语句。初始化后,可升级读锁将允许多个线程,因此不会出现等待每个线程的性能损失。

我还在这里阅读了一篇文章,说 volatile 会导致在读取之前和写入之后自动插入内存屏障,因此我假设在读取和写入之间只有一个手动定义的屏障就足以确保正确读取 _valueReference 对象。我很乐意感谢您对使用这种方法的建议和批评。

0 投票
2 回答
299 浏览

java - 具有双重检查锁定和空处理的 LazyReference

我已经使用LazyReference类几年了(当然不是定期使用,但有时它非常有用)。课程可以在这里看到。归功于 Robbie Vanbrabant(课程作者)和 Joshua Bloch 以及他著名的“Effective Java 2nd edt”。(原始代码)。

该类可以正常工作(在 Java 5+ 中),但存在一个小问题。如果instanceProvider返回null(当然它不能根据 GuiceProvider.get()合同,但是......)然后在每次执行LazyReference.get()方法时,LOCK 将被持有并被instanceProvider.get一遍又一遍地调用。对于那些违反合同的人来说,这似乎是一种很好的惩罚(he-he),但如果真的需要懒惰地初始化一个可以设置null值的字段怎么办?

我稍微修改了 LazyReference:

恕我直言,它应该可以正常工作(如果您有其他意见,请发表您的评论和批评)。但是我想知道如果我volatile从布尔值中删除修饰符会发生什么isNull(当然保留它instance)?它还能正常工作吗?

0 投票
6 回答
3980 浏览

java - 使用 ConcurrentMap 进行双重检查锁定

我有一段代码可以由多个线程执行,需要执行 I/O 绑定操作才能初始化存储在ConcurrentMap. 我需要使这个代码线程安全并避免不必要的调用来初始化共享资源。这是错误的代码:

使用上面的代码,多个线程可能会检查ConcurrentMap并看到资源不存在,并且都尝试调用getResource()代价高昂的资源。为了确保仅对共享资源进行一次初始化并在资源初始化后使代码高效,我想做这样的事情:

这是双重检查锁定的安全版本吗?在我看来,由于调用了检查ConcurrentMap,它的行为就像一个被声明为的共享资源,volatile因此可以防止任何可能发生的“部分初始化”问题。

0 投票
2 回答
1559 浏览

c# - 是否应该将此 C# 代码重构为使用 Lazy代替上课?

我有以下代码,可以同时通过多个网络请求调用。因此,我不希望第二个+请求命中数据库,而是等到第一个请求。

我应该重构它以使用Lazy<T> 关键字类吗?如果Lazy<T>同时发生对一段代码的 10 次调用,那么其中 9 次调用会等待第一个调用完成吗?

0 投票
7 回答
28051 浏览

java - 为什么在双重检查锁定中使用volatile

Head First设计模式一书中,具有双重检查锁定的单例模式已实现如下:

我不明白为什么volatile被使用。使用是否会破坏 volatile使用双重检查锁定的目的,即性能?

0 投票
2 回答
1365 浏览

c++ - 延迟初始化缓存...如何使其成为线程安全的?

这就是我所拥有的:

  • Windows 服务
    • C#
    • 多线程
    • 该服务使用读写锁(一次多次读取,写入阻塞其他读/写线程)
  • 一个简单的自写数据库
    • C++
    • 小到可以放入内存
    • 足够大,不想在启动时加载它(例如 10GB)
    • 读取性能非常重要
    • 写作不那么重要
    • 树状结构
    • 树节点中保存的信息存储在文件中
    • 为了获得更快的性能,文件仅在第一次使用和缓存时加载
    • 延迟初始化以加快数据库启动

由于数据库会经常访问这些节点信息(每秒几千次),而且我不经常写,我想使用某种双重检查锁定模式。

我知道这里有很多关于双重检查锁定模式的问题,但似乎有很多不同的意见,所以我不知道什么是最适合我的情况。你会用我的设置做什么?

这是一个例子:

  • 一棵有 100 万个节点的树
  • 每个节点存储一个键值对列表(存储在一个文件中用于持久性,文件大小大小:10kB)
  • 当第一次访问一个节点时,列表被加载并存储在一个地图中(比如std::map)
  • 下次访问这个节点的时候,我就不用再加载文件了,直接从map中获取就可以了。
  • 唯一的问题:两个线程第一次同时访问该节点并想要写入缓存映射。这不太可能发生,但也不是不可能。这就是我需要线程安全的地方,这不应该花费太多时间,因为我通常不需要它(尤其是当整个数据库都在内存中时)。
0 投票
3 回答
422 浏览

java - 此代码双重检查锁定安全吗?

我正在查看我们应用程序中的一些代码,我认为这些代码可能会遇到“双重检查锁定”的情况。我已经编写了一些与我们所做的类似的示例代码。

谁能看到这是如何经历双重检查锁定的?或者这样安全吗?

从wiki借来的基本代码。

0 投票
3 回答
744 浏览

java - 双重检查锁定,NetBeans 把我搞糊涂了?

我有一个关于双重检查锁定的问题。考虑这个例子:

据我了解,上面的代码是制作单例类的正确方法。

但是,NetBeans 希望我删除外部 if 语句,所以它看起来像这样:

这两个片段之间的唯一区别是,在第二个示例中,代码将始终进入同步块,而在第一个示例中则不会。为什么我要听 NetBeans 并删除外部 if 语句?最好避免锁定。