相关疑难解决方法(0)

.NET中双重检查锁定需要volatile修饰符

多个文本说,当在.NET中实现双重检查锁定时,您锁定的字段应该应用volatile修饰符.但为什么呢?考虑以下示例:

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }

         return instance;
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

为什么不"锁定(syncRoot)"完成必要的内存一致性?在"lock"语句之后,读取和写入都是不稳定的,因此必须实现必要的一致性,这不是真的吗?

c# singleton volatile

80
推荐指数
4
解决办法
2万
查看次数

C++ 11中的Double-Checked Lock Singleton

以下单例实现数据 - 竞争是免费的吗?

static std::atomic<Tp *> m_instance;
...

static Tp &
instance()
{
    if (!m_instance.load(std::memory_order_relaxed))
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        if (!m_instance.load(std::memory_order_acquire))
        {
            Tp * i = new Tp;
            m_instance.store(i, std::memory_order_release);    
        }    
    }

    return * m_instance.load(std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)

是std::memory_model_acquire了负载运行的多余?是否可以通过将它们切换到进一步放宽加载和存储操作std::memory_order_relaxed?在这种情况下,获取/释放语义是否std::mutex足以保证其正确性,或者std::atomic_thread_fence(std::memory_order_release)还需要确保构造函数的内存写入在轻松存储之前发生?然而,使用栅栏相当于有商店memory_order_release吗?

编辑:感谢John的回答,我提出了以下应该是数据竞争的实现.尽管内部负载可能完全是非原子的,但我决定放弃一个宽松的负载,因为它不会影响性能.与总是具有获取存储器顺序的外部负载相比,thread_local机器提高了访问大约一个数量级的实例的性能.

static Tp &
instance()
{
    static thread_local Tp *instance;

    if (!instance && 
        !(instance = m_instance.load(std::memory_order_acquire)))
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        if (!(instance = m_instance.load(std::memory_order_relaxed)))
        {
            instance = new Tp; 
            m_instance.store(instance, std::memory_order_release);    
        }    
    }
    return …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading atomic c++11

43
推荐指数
3
解决办法
1万
查看次数

C++中单例的线程安全延迟构造

有没有办法在C++中实现单例对象:

  1. 懒惰地以线程安全的方式构造(两个线程可能同时是单例的第一个用户 - 它应该仍然只构造一次).
  2. 不依赖于事先构造的静态变量(因此单例对象在构造静态变量期间本身是安全的).

(我不太了解我的C++,但是在执行任何代码之前初始化积分和常量静态变量的情况(即,甚至在执行静态构造函数之前 - 它们的值可能已在程序中"初始化")如果是这样的话 - 也许这可以被利用来实现单例互斥体 - 这反过来可以用来保护真正的单例的创建......)


很好,现在我似乎有几个好的答案(羞耻我不能标记2或3作为答案).似乎有两个广泛的解决方案:

  1. 使用POD静态变量的静态初始化(而不是动态初始化),并使用内置原子指令实现我自己的互斥锁.这是我在问题中暗示的那种解决方案,我相信我已经知道了.
  2. 使用其他库函数,如pthread_once或boost :: call_once.这些我当然不知道 - 并且非常感谢所发布的答案.

c++ singleton construction multithreading lazy-initialization

36
推荐指数
5
解决办法
2万
查看次数

如何解决Java中的"双重检查锁定"声明?

我想在Java中实现多线程的延迟初始化.
我有一些类似的代码:

class Foo {
    private Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            Helper h;
            synchronized(this) {
                h = helper;
                if (h == null) 
                    synchronized (this) {
                        h = new Helper();
                    } // release inner synchronization lock
                helper = h;
            } 
        }    
        return helper;
    }
    // other functions and members...
}
Run Code Online (Sandbox Code Playgroud)

而且我得到了"Double-Checked Locking is Broken"声明.
我怎么解决这个问题?

java concurrency multithreading locking lazy-loading

33
推荐指数
3
解决办法
2万
查看次数

双重检查锁定模式:是否破碎?

为什么模式被认为是破碎的?它看起来很好吗?有任何想法吗?

public static Singleton getInst() {
    if (instace == null) createInst();
    return instace;
}

private static synchronized createInst() {
     if (instace == null) {
         instace = new Singleton(); 
     }
}
Run Code Online (Sandbox Code Playgroud)

java concurrency singleton double-checked-locking

9
推荐指数
4
解决办法
2731
查看次数

这是双重检查锁定吗?

Checkstyle将此代码报告为"双重检查锁定习语已损坏",但我认为我的代码实际上并未受到双重检查锁定问题的影响.

如果不存在具有该id的行,则该代码应该在数据库中创建一行.它在多线程环境中运行,我想避免主键存在的SQL异常.

伪代码:

private void createRow(int id) {
  Row row = dao().fetch(id);
  if (row == null) {
     synchronized (TestClass.class) {
        row = dao().fetch(id);
        if (row == null) {
           dao().create(id);
        }
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以同意它看起来像双重检查锁定,但我没有使用静态变量,fetch()和create()中的代码可能太复杂,无法内联并使其无序.

我错了还是格式?:)

java synchronization locking double-checked-locking

5
推荐指数
2
解决办法
1957
查看次数

双重锁定从checkstyle中消失 - 为什么?

从发行说明中,checkstyle删除了Double-Checked锁定检查.

我很难理解为什么.他们不仅在发布说明中回复了这个问题,而且还在问题跟踪器中回复:

删除DoubleCheckedLocking检查,如在Java 5(及更高版本)中,使用volatile关键字解决问题.

我假设,如果checkstyle正在删除此警告,那是因为它不再有用.也就是说,错误将不再发生或另一个警告完成工作.但

我不明白为什么在Java 5中不再发生这样的错误,或者它是如何被另一个警告补充的.有人可以解释一下吗?

编辑:我理解添加volatile关键字如何解决问题.我担心的是:这个警告不是值得的吗?我正在考虑程序员使用上述锁定模式的情况,但忘记声明变量volatile.checkstyle还不应警告它吗?

java checkstyle double-checked-locking

3
推荐指数
1
解决办法
2949
查看次数