从Head First设计模式书中,具有双重检查锁定的单例模式已实现如下:
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么volatile被使用.volatile使用不会 破坏使用双重检查锁定的目的,即性能?
java singleton design-patterns locking double-checked-locking
我在本文中讨论了为什么在Java中打破了双重检查锁定范例的原因.如果声明变量,范例是否对.NET(特别是C#)有效volatile?
我在java中看到了一些例子,他们在一块代码上做同步来改变一些变量,而这个变量最初被声明为volatile.我在单例类的一个例子中看到,他们将唯一的实例声明为volatile并且他们同步了块初始化那个实例...我的问题是为什么我们在同步它时声明它是不稳定的,为什么我们需要同时做两个?对其他人来说不是其中之一吗?
public class someClass {
volatile static uniqueInstance = null;
public static someClass getInstance() {
if(uniqueInstance == null) {
synchronized(someClass.class) {
if(uniqueInstance == null) {
uniqueInstance = new someClass();
}
}
}
return uniqueInstance;
}
Run Code Online (Sandbox Code Playgroud)
提前致谢.
java multithreading volatile synchronized double-checked-locking
我碰巧发表了一篇文章,最近讨论了Java中的双重检查锁定模式及其陷阱,现在我想知道我多年来一直使用的那种模式的变体是否会受到任何问题的影响.
我已经查看了很多关于这个主题的帖子和文章,并了解了获取对部分构造对象的引用的潜在问题,据我所知,我认为我的实现不受这些问题的影响.以下模式是否有任何问题?
而且,如果没有,为什么人们不使用它?我在这个问题的任何讨论中都没有看过它.
public class Test {
private static Test instance;
private static boolean initialized = false;
public static Test getInstance() {
if (!initialized) {
synchronized (Test.class) {
if (!initialized) {
instance = new Test();
initialized = true;
}
}
}
return instance;
}
}
Run Code Online (Sandbox Code Playgroud) java singleton multithreading synchronization double-checked-locking
private volatile static Singleton uniqueInstance
Run Code Online (Sandbox Code Playgroud)
在单独使用双锁方法进行同步时,为什么单个实例声明为volatile?我可以在不将其声明为volatile的情况下实现相同的功能吗?
java singleton volatile double-checked-locking thread-synchronization
我看了这个问题,如何做双检锁:
// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我的目标是在没有volatile属性的情况下延迟加载字段(而不是单例).初始化后,字段对象永远不会更改.
经过一些测试我的最终方法:
private FieldType field;
FieldType getField() {
if (field == null) {
synchronized(this) {
if (field == null)
field = Publisher.publish(computeFieldValue());
} …Run Code Online (Sandbox Code Playgroud) java multithreading final java-memory-model double-checked-locking
根据许多人的说法,除非你运行1.5或更高版本并使用volatile关键字,否则java会破坏一些常见的Double-Checked Locking成语.
一个破损的双重检查锁定样本:
// Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null)
synchronized(this) {
if (helper == null)
helper = new Helper();
}
return helper;
}
// other functions and members...
}
Run Code Online (Sandbox Code Playgroud)
该示例来自本文,其中还提供了有关如何修复它的详细信息:http: //www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Pugh上面的分析是针对Java VM的.我在Android上工作并经常使用采用Double-Checked Locking的库.dalvik VM的内存模型是否支持这个习惯用法?
我的团队目前正在讨论这个问题.
有问题的代码就是这样的
if (!myDictionary.ContainsKey(key))
{
lock (_SyncObject)
{
if (!myDictionary.ContainsKey(key))
{
myDictionary.Add(key,value);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我见过的一些帖子说这可能是一个很大的NO NO(当使用TryGetValue时).然而,我们团队的成员说没关系,因为"ContainsKey"不会对密钥集合进行迭代,而是通过O(1)中的哈希代码检查密钥是否包含在内.因此他们声称这里没有危险.
我想就此问题得到您的诚实意见.
c# collections multithreading dictionary double-checked-locking
我需要懒洋洋地初始化地图及其内容.我现在有以下代码:
class SomeClass {
private Map<String, String> someMap = null;
public String getValue(String key) {
if (someMap == null) {
synchronized(someMap) {
someMap = new HashMap<String, String>();
// initialize the map contents by loading some data from the database.
// possible for the map to be empty after this.
}
}
return someMap.get(key); // the key might not exist even after initialization
}
}
Run Code Online (Sandbox Code Playgroud)
这显然不是线程安全的,如果一个线程来的时候someMap是空,继续初始化领域new HashMap和而其仍然在地图加载数据,另一个线程做了getValue,并没有得到数据时,人们可能已经存在.
如何在第一次getValue调用时确保数据仅在地图中加载一次.
请注意,key在所有初始化之后,地图中可能不存在.此外,在所有初始化之后,地图可能只是空的.
对于线程安全的延迟初始化,是否应该更喜欢函数内部的静态变量,std :: call_once或显式双重检查锁定?有什么有意义的差异吗?
在这个问题中可以看到这三个.
C++ 11中的Double-Checked Lock Singleton
在Google中出现了两个版本的C++ 11双重检查锁定版本.
Anthony Williams 使用显式内存排序和std :: call_once 显示双重检查锁定.他没有提到静态,但该文章可能是在C++ 11编译器可用之前编写的.
杰夫Preshing,在广泛的书面记录,描述了双重检查锁定的几个变化.他确实提到使用静态变量作为选项,他甚至表明编译器将生成用于双重检查锁定的代码以初始化静态变量.我不清楚他是否认为一种方式比另一种更好.
我觉得这两篇文章都是教学的,没有理由这样做.如果您使用静态变量或std :: call_once,编译器将为您执行此操作.
java ×7
singleton ×3
dictionary ×2
volatile ×2
.net ×1
android ×1
c# ×1
c++ ×1
c++11 ×1
collections ×1
dalvik ×1
final ×1
locking ×1
paradigms ×1
synchronized ×1