Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net NET中的双重检查锁定_.net_Multithreading_Paradigms_Double Checked Locking - Fatal编程技术网

.net NET中的双重检查锁定

.net NET中的双重检查锁定,.net,multithreading,paradigms,double-checked-locking,.net,Multithreading,Paradigms,Double Checked Locking,我看到一篇文章讨论了为什么双重检查锁定范式在Java中被打破。如果变量声明为volatile,在第三个版本中讨论了这个问题,那么这个范例对.NET(特别是C#)有效吗 它说: 使实例变量变为volatile可以使其工作,就像显式内存障碍调用一样,尽管在后一种情况下,即使专家也不能确切地同意需要哪些障碍。我倾向于避免专家不同意什么是对的什么是错的情况 作者似乎暗示,与其他策略相比,双重锁定不太可能起作用,因此不应使用。注意,与Java(以及最有可能的.Net)相比,用于单例初始化的双重检查锁定是完

我看到一篇文章讨论了为什么双重检查锁定范式在Java中被打破。如果变量声明为
volatile
,在第三个版本中讨论了这个问题,那么这个范例对.NET(特别是C#)有效吗

它说:

使实例变量变为volatile可以使其工作,就像显式内存障碍调用一样,尽管在后一种情况下,即使专家也不能确切地同意需要哪些障碍。我倾向于避免专家不同意什么是对的什么是错的情况

作者似乎暗示,与其他策略相比,双重锁定不太可能起作用,因此不应使用。

注意,与Java(以及最有可能的.Net)相比,用于单例初始化的双重检查锁定是完全不必要的,也是不必要的。因为类在第一次使用之前是不会初始化的,所以通过这种方式已经实现了所需的延迟初始化

private static Singleton instance = new Singleton();

除非您的Singleton类包含在首次使用Singleton实例之前可以访问的常量之类的内容,否则这就是您需要做的全部工作。

双重检查锁定现在在Java和C#中都可以工作(Java内存模型发生了变化,这是影响之一)。然而,你必须完全正确。如果你把事情搞得一团糟,你很可能会失去线程的安全性


正如其他答案所述,如果您正在实施,那么有更好的方法来实现它。就我个人而言,如果我必须在自己实现双重检查锁定和“每次锁定”代码之间做出选择,我会每次都锁定,直到我得到真正的证据证明这是造成瓶颈的原因。当谈到线程时,一个简单且明显正确的模式是非常有价值的。

.NET4.0有一种新类型:
Lazy
,它消除了任何关于模式出错的顾虑。它是新任务并行库的一部分

请参阅MSDN并行计算开发中心:


顺便说一句,有一个用于.NET 3.5 SP1的后端口(我相信它不受支持)。

我通过使用布尔值(即使用原语避免延迟初始化)获得了双重检查锁定:


我已经通过使用布尔值(即使用原语来避免延迟初始化)实现了双重检查锁定:

使用布尔值的单例不起作用。除非您通过内存屏障,否则无法保证不同线程之间的操作顺序。 换句话说,从第二条线来看,
created=true
可以在
instance=new Singleton()之前执行

我不太明白为什么在双重检查锁定上有一堆实现模式(显然是为了解决各种语言中的编译器特性)。Wikipedia关于这个主题的文章展示了天真的方法和解决问题的可能方法,但没有一个像这样简单(用C#):

在Java中,使用synchronized()而不是lock(),但基本上是相同的想法。如果分配单例字段的时间可能不一致,那么为什么不首先使用一个局部范围的变量,然后在退出临界段之前的最后一个可能时刻分配单例字段呢?我错过什么了吗


@michael borgwardt认为,在C#和Java中,静态字段只在第一次使用时初始化一次,但认为行为是特定于语言的。我经常使用这种模式对集合属性(例如user.Sessions)进行延迟初始化。

我不明白为什么所有人都说双重检查锁定是一种糟糕的模式,但不调整代码使其正常工作。在我看来,下面的代码应该可以正常工作

如果有人能告诉我这段代码是否存在Cameron文章中提到的问题,请告诉我

public sealed class Singleton {
    static Singleton instance = null;
    static readonly object padlock = new object();

    Singleton() {
    }

    public static Singleton Instance {
        get {
            if (instance != null) {
                return instance;
            }

            lock (padlock) {
                if (instance != null) {
                    return instance;
                }

                tempInstance = new Singleton();

                // initialize the object with data

                instance = tempInstance;
            }
            return instance;
        }
    }
}

DCL从Java5开始就可以工作(请参见JonSkeet的评论,尽管他并没有具体说明您必须做些什么才能使其工作)。你需要:1。爪哇5。2.DCL引用声明为volatile(或者在某种程度上是原子的,例如使用AtomicReference)。有关Java单例和DCL模式,请参阅中的“在新Java内存模型下”一节。请参阅此链接@Jon:问题中的文章指出,
volatile
有助于JDK5+。那.NET呢?
volatile
是否足以在.NET1.1上实现正确的双重检查锁定?(例如,您文章中的“第三个版本-尝试使用双重检查锁定的线程安全”示例如何:当
volatile
放在
instance
static字段上时,它在技术上是“修复”的吗?@IgorK:是的,我相信当变量标记为volatile时它会起作用。@Jon:好的,谢谢。至少对于单身人士来说,我们确实有更好的解决方案。@Myster:我个人总是会把锁取出来,尤其是当你做其他一些慢动作时,这使得锁的成本变得微不足道。@Myster:我说的“取下锁”是指“获得锁”。我发现它是不明确的:)是的,删除外部检查。双重检查锁定的问题是实例可能是非null的,但仍然没有初始化。因此,即使对象尚未初始化,同步块之外的线程也可以通过初始(未同步)null检查。上面的代码通过检查布尔值来解决这个问题。当created=true被命中时,我们知道实例已经初始化,因此同步块外的线程无法获得未初始化的实例。人们之所以说它不好,是因为它极易出错。我认为您的代码在
实例
成员上需要一个
volatile
。(至少在这种情况下,代码是否有效不是一个意见问题,而是一个事实问题。我认为事实是它不起作用,但我可能在这一点上错了)。@erikkallen没有必要在.NET中使用volatile。别忘了.NETH
public class Foo
{
  static Foo _singleton = null;
  static object _singletonLock = new object();

  public static Foo Singleton
  {
    get
    {
      if ( _singleton == null )
        lock ( _singletonLock )
          if ( _singleton == null )
          {
            Foo foo = new Foo();

            // Do possibly lengthy initialization,
            // but make sure the initialization
            // chain doesn't invoke Foo.Singleton.
            foo.Initialize();

            // _singleton remains null until
            // object construction is done.
            _singleton = foo;
          }
      return _singleton;
    }
  }
public sealed class Singleton {
    static Singleton instance = null;
    static readonly object padlock = new object();

    Singleton() {
    }

    public static Singleton Instance {
        get {
            if (instance != null) {
                return instance;
            }

            lock (padlock) {
                if (instance != null) {
                    return instance;
                }

                tempInstance = new Singleton();

                // initialize the object with data

                instance = tempInstance;
            }
            return instance;
        }
    }
}