标签: double-checked-locking

Mike Ash Singleton:放置@synchronized

我在Mike Ash的"照顾和喂养单身人士"中遇到了这个问题,他的评论有点困惑:

不过,这段代码有点慢.拿锁是有点贵的.令人痛苦的是,在绝大多数情况下,锁定毫无意义.只有当foo为nil时才需要锁定,这基本上只发生一次.在单例初始化之后,对锁的需求消失了,但锁本身仍然存在.

+(id)sharedFoo {
    static Foo *foo = nil;
    @synchronized([Foo class]) {
        if(!foo) foo = [[self alloc] init];
    }
    return foo;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,毫无疑问这是一个很好的理由,但为什么你不能写(见下文)来限制当foo为零时的锁定?

+(id)sharedFoo {
    static Foo *foo = nil;
    if(!foo) {
        @synchronized([Foo class]) {
            foo = [[self alloc] init];
        }
    }
    return foo;
}
Run Code Online (Sandbox Code Playgroud)

欢呼加里

cocoa objective-c double-checked-locking

7
推荐指数
2
解决办法
4038
查看次数

HashMap缓存中的同步

我有一个人们要求资源的网络应用程序.为了提高效率,使用同步哈希映射缓存此资源.这里的问题是当同时为同一个未缓存的资源发出两个不同的请求时:检索资源的操作会占用大量内存,所以我想避免为同一个资源多次调用它.

有人可以告诉我,以下代码段是否存在任何潜在问题?提前致谢.

private Map<String, Resource> resources = Collections.synchronizedMap(new HashMap<String, Resource>());

public void request(String name) {

  Resource resource = resources.get(name);

  if (resource == null) {
    synchronized(this) {
      if (resources.get(name) == null) {
        resource = veryCostlyOperation(name); // This should only be invoked once per resource...
        resources.put(resource);
      } else {
        resource = resources.get(name);
      }
    }
  }

  ...

}
Run Code Online (Sandbox Code Playgroud)

java multithreading synchronization caching double-checked-locking

7
推荐指数
1
解决办法
5149
查看次数

Threadsafe Singleton没有Java同步?

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

public final class Singleton {

    private static MyClass mc;

    public static final Object getInstance() {
            if(mc == null) {
                mc = new MyClass();
            }
            return mc;
    }

}
Run Code Online (Sandbox Code Playgroud)

当然,这在一般的多线程场景中不起作用.但请考虑以下情形:

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

我的假设:

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

这个假设是对的吗?为什么/为什么不呢?

java singleton multithreading double-checked-locking

7
推荐指数
1
解决办法
571
查看次数

没有 volatile 的双重检查锁定(但带有 VarHandle 释放/获取)

在某种程度上,这个问题相当简单。假设我有这个类:

static class Singleton {

}
Run Code Online (Sandbox Code Playgroud)

我想为它提供一个单例工厂。我可以做(可能)显而易见的事情。我不打算提及枚举的可能性或任何其他可能性,因为我对它们不感兴趣。

static final class SingletonFactory {

    private static volatile Singleton singleton;

    public static Singleton getSingleton() {
        if (singleton == null) { // volatile read
            synchronized (SingletonFactory.class) {
                if (singleton == null) { // volatile read
                    singleton = new Singleton(); // volatile write
                }
            }
        }
        return singleton; // volatile read
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以volatile read以更高的代码复杂性为代价摆脱一个:

public static Singleton improvedGetSingleton() {
    Singleton local = singleton; // volatile read
    if (local == null) {
        synchronized …
Run Code Online (Sandbox Code Playgroud)

java concurrency volatile double-checked-locking

7
推荐指数
1
解决办法
202
查看次数

在现实世界的Java应用程序中单例模式和破坏双重检查锁定

我正在阅读文章Double-checked locking和Singleton模式,关于双重检查锁定如何被破坏,以及Stack Overflow上的一些相关问题.

我已经多次使用这种模式/习语而没有任何问题.由于我一直在使用Java 5,我首先想到的是这已经在Java 5内存模型中得到了纠正.然而文章说:

本文引用了Java 5.0之前的Java内存模型; 关于内存排序的陈述可能不再正确.然而,在新的内存模型下,双重检查的锁定习惯仍然被打破.

这是一个真正的问题,如果是这样,在什么条件下?

java singleton double-checked-locking

6
推荐指数
1
解决办法
9307
查看次数

Java synchronized关键字是否刷新缓存?

仅限Java 5及以上版本.假设一个多处理器共享内存计算机(你现在可能正在使用它).

这是一个单例的延迟初始化代码:

public final class MySingleton {
  private static MySingleton instance = null;
  private MySingleton() { } 
  public static MySingleton getInstance() {
    if (instance == null) {
      synchronized (MySingleton.class) {
        if (instance == null) {
          instance = new MySingleton();
        }
      }
    }
    return instance;
  }
}
Run Code Online (Sandbox Code Playgroud)

是否instance必须声明volatile,以阻止优化重写的getInstance()如下(这将是一个连续的程序是正确的):

public static MySingleton getInstance() {
  if (instance == null) {
    synchronized (MySingleton.class) {
      // instance must be null or we wouldn't be here  (WRONG!)
      instance = new MySingleton(); …
Run Code Online (Sandbox Code Playgroud)

java volatile synchronized double-checked-locking

6
推荐指数
1
解决办法
2280
查看次数

PHP线程和同步

我是PHP的新手,所以要开始我已经决定实现一个单例.

虽然我能够在php中重新创建单例模式,但我不确定如何实现双重检查锁定.

这在PHP中是否可行/需要.我在某处读过PHP不是多线程的?有人可以证实吗?

如果它是多线程的,有人可以向我解释一下lock()或synchronize()在PHP中是如何工作的吗?

谢谢,亨利

php singleton multithreading synchronize double-checked-locking

6
推荐指数
1
解决办法
5865
查看次数

双重锁定时,为什么Immutable Objects是安全的?

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html的底部,它说:

双重检查锁定不可变对象

如果Helper是一个不可变对象,使得Helper的所有字段都是最终的,那么双重检查锁定将无需使用volatile字段即可工作.我们的想法是对不可变对象(如String或Integer)的引用应该与int或float的行为方式大致相同; 读取和写入对不可变对象的引用是原子的.

可变的样本和解释如下:

// 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)

它不起作用的第一个原因

最明显的原因是,初始化Helper对象和写入辅助对象字段的写入可以无序完成或感知.因此,调用getHelper()的线程可以看到对辅助对象的非null引用,但是请参阅辅助对象的字段的默认值,而不是构造函数中设置的值.

如果编译器内联对构造函数的调用,那么如果编译器可以证明构造函数不能抛出异常或执行同步,则可以自由地重新排序初始化对象和写入辅助对象字段的写入.

即使编译器没有重新排序这些写入,在多处理器上,处理器或内存系统也可能重新排序这些写入,正如在另一个处理器上运行的线程所感知的那样.

我的问题是:为什么不可变类没有问题?我看不出重新排序与该类是否可变的任何关系.

谢谢

java immutability thread-safety double-checked-locking

6
推荐指数
1
解决办法
419
查看次数

我的Double-Checked Locking Pattern实现是否合适?

Meyers的书" Effective Modern C++ "第16项中的一个例子.

在一个缓存昂贵的计算int的类中,您可能会尝试使用一对std :: atomic avriable而不是互斥锁:

class Widget {
public:
    int magicValue() const {
        if (cachedValid) {
            return cachedValue;
        } else {
            auto val1 = expensiveComputation1();
            auto val2 = expensiveComputation2();

            cachedValue = va1 + val2;
            cacheValid = true;
            return cachedValue;
        }
    }
private:
    mutable std::atomic<bool> cacheValid { false };
    mutable std::atomic<int> cachedValue;
};
Run Code Online (Sandbox Code Playgroud)

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

然后他用互斥量给出了一个解决方案:

class Widget {
public:
    int magicValue() const {
        std::lock_guard<std::mutex> guard(m);
        if (cacheValid) {
            return cachedValue;
        } else …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading mutex atomic double-checked-locking

6
推荐指数
1
解决办法
310
查看次数

使用常规HashMap双重检查锁定

回到并发.到目前为止,很明显,为了double checked locking工作,需要将变量声明为volatile.但是,如果使用双重检查锁定,如下所示.

class Test<A, B> {

    private final Map<A, B> map = new HashMap<>();

    public B fetch(A key, Function<A, B> loader) {
        B value = map.get(key);
        if (value == null) {
            synchronized (this) {
                value = map.get(key);
                if (value == null) {
                    value = loader.apply(key);
                    map.put(key, value);
                }
            }
        }
        return value;
    }

}
Run Code Online (Sandbox Code Playgroud)

为什么它必须是ConcurrentHashMap而不是常规的HashMap?所有映射修改都在synchronized块内完成,代码不使用迭代器,因此从技术上讲,应该没有"并发修改"问题.

请避免建议使用putIfAbsent/,computeIfAbsent因为我询问的概念而不是API的使用:)除非使用此API有助于HashMapvs ConcurrentHashMapsubject.

更新2016-12-30

这个问题由Holger下面的评论回答" HashMap.get …

java concurrency hashmap concurrenthashmap double-checked-locking

6
推荐指数
1
解决办法
1332
查看次数