问题标签 [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.
java - 为什么在单例类的情况下双重检查锁定不会像这样失败?
这种结构被认为是损坏的原因通常描述为编译器完成的赋值重新排序,以便在写入助手变量后调用助手构造函数。我的问题是,这段代码是如何线程安全的,以下步骤是否可行?
- 线程 1,进入同步块,发现 helper 为空。
- 线程1,此时放弃监视器
- 线程2,进入对象监视器并实例化助手
- 线程 1,返回并重新初始化助手实例
我看不出这个解决方案比单检查锁定更好。
java - Map synchronization with double check locking
I've read about double-checked locking and its drawbacks, but I'm asking if using a synchronizedMap
can be considered safe.
Here is my code:
Suggestions or improvements are welcome.
java - 非静态值的延迟初始化
这个问题实际上是指一个不同的问题,因为它可能没有很好地表述,所以它被关闭为重复。
对于此代码示例(在多线程环境中),什么是有效的替代惰性初始化习惯用法而不是双重检查锁定:
}
编辑更新以包括一个缓慢的操作并添加了关于多线程环境的明确提及
java - Java 可以在对象被某种方法构造之前写入对象的引用吗?
使用双重检查锁定模式时有一个众所周知的陷阱(示例和解释摘自“实践中的并发”):
某些线程可能会看到“资源”变量的初始化值,而对象本身仍在构建中。
一个问题是:如果我们以某种方法构造资源对象,问题是否仍然存在?IE
当资源对象仍在 createResource() 方法中构建时,某些线程可以将资源 != null 评估为 true 吗?
java - 非易失性双重检查锁定,有可能吗?
这是我的单身课程。
静态instance
字段不是易失性的,因此会出现重新排序/可见性问题。为了解决它,实例val
字段被设置为最终字段。val
由于实例是正确构造的,因此如果他们看到实例,它的客户应该总是看到已初始化的字段。
但是还有另一个问题 - 我有两个不受保护的“实例”字段读取,可以(?)重新排序,以便客户端可能得到 null 而不是实际值:
为了解决这个问题,我觉得我可以引入局部变量:
这似乎解决了这个问题,因为只有一个不受保护的值读取,所以不会发生真正的邪恶。但是......我刚刚修改了程序流程,而没有(几乎?)改变它的单线程语义。这是否意味着编译器可以撤消我的解决方法,因为这种转换是安全的,并且如果不与 volatile 建立适当的先发生关系,就无法使此代码工作?
c# - 多次调用 PreApplicationStartMethod
由属性修饰的程序集中的类中的方法意味着在触发事件PreApplicationStartMethod
之前调用。Application_Start
例如,这是了解BuildManager
在编译页面、控件或视图时要引用哪些程序集(除了 Web 应用程序中的程序集)的方法。
期望指出的方法只被调用一次是很自然的——毕竟它是初始化过程的一部分,通常每个应用程序只发生一次。(我只会提到两次创建数据库的尝试!!)
添加一些跟踪调用后,我发现该方法(并非总是如此,有时!)被调用了两次。为了避免这种情况,我在类中添加了一个布尔字段以防止像这样的多次调用:
令我惊讶的是,该方法又被调用了两次。一个明显的怀疑是它是在两个不同的线程上调用的(尽管这在初始化代码中有点意义)。 双重检查锁定是解决此类问题的明显方法,因此我将代码更改为:
真正使这个问题成为问题的是代码是从本机代码调用的事实。这是来自跟踪点的 $CALLER:
所以,我的问题很明显,我猜:是什么(更重要的是为什么!)调用了一个表示在Application_Start
事件之前多次调用的方法?
c++ - 线程安全延迟初始化:静态 vs std::call_once vs 双重检查锁定
对于线程安全的延迟初始化,应该更喜欢函数内的静态变量、std::call_once,还是显式的双重检查锁定?有什么有意义的区别吗?
这三个都可以在这个问题中看到。
Google 中出现了两个版本的 C++11 中的双重检查锁定。
Anthony Williams展示了带有显式内存排序的双重检查锁定和 std::call_once。他没有提到静态,但那篇文章可能是在 C++11 编译器可用之前编写的。
Jeff Preshing在一篇广泛的文章中描述了双重检查锁定的几种变体。他确实提到了使用静态变量作为选项,他甚至表明编译器将生成用于双重检查锁定的代码以初始化静态变量。我不清楚他是否认为一种方法比另一种更好。
我觉得这两篇文章都是为了教学,没有理由这样做。如果您使用静态变量或 std::call_once,编译器将为您执行此操作。
java - 双重检查锁定的特殊情况?
所以我有这个代码,其中 lockMap 是ConcurrentHashMap
在代码审查期间,有人提到这是 DCL 的典型案例,因为由于编译器可以对事件进行重新排序,因此锁在插入映射时可能尚未完全初始化,那么下一个请求相同锁的线程可能可能尚未完全初始化。
现在,我遇到的问题是这个问题是多线程应用程序的常见问题:从地图中获取一些东西,如果没有,则创建并添加。
- 这真的是DCL的案例吗?
- 如果是这样,你如何解决它。(我们使用的简单而愚蠢的方法是创建一个锁池,当从池中提取一个锁时,插入一个新锁)
- 如果又是这样,它是否已在 java8 中修复
java - 为什么不可变对象在双重检查锁定中是安全的?
在http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html的底部,它说:
双重检查锁定不可变对象
如果 Helper 是一个不可变对象,这样 Helper 的所有字段都是最终的,那么双重检查锁定将起作用,而不必使用 volatile 字段。这个想法是对不可变对象(如字符串或整数)的引用应该与 int 或 float 的行为方式大致相同;对不可变对象的读写引用是原子的。
mutable one的示例和解释如下:
第一个原因,它不起作用
最明显的原因是初始化 Helper 对象的写入和对 helper 字段的写入可以完成或被认为是无序的。因此,调用 getHelper() 的线程可以看到对辅助对象的非空引用,但会看到辅助对象的字段的默认值,而不是构造函数中设置的值。
如果编译器内联对构造函数的调用,那么如果编译器可以证明构造函数不能抛出异常或执行同步,则初始化对象的写入和对辅助字段的写入可以自由地重新排序。
即使编译器不重新排序这些写入,在多处理器上,处理器或内存系统也可能重新排序这些写入,正如在另一个处理器上运行的线程所感知的那样。
我的问题是:为什么不可变类没有问题?我看不到重新排序与类是否可变的任何关系。
谢谢