C# 单例实现可以在32位上正常工作,但不能在64位上正常工作

C# 单例实现可以在32位上正常工作,但不能在64位上正常工作,c#,multithreading,64-bit,singleton,C#,Multithreading,64 Bit,Singleton,我正在使用一个共享对象开发一个应用程序,该对象可以通过单例访问。它在32位上工作正常,但在64位上似乎没有正确锁定。在我的对象的构造函数中,我有一些代码,用于检查一些config reg键,并在它们不存在时提示用户。在32位上,我只会像预期的那样看到一次提示,但在64位上,提示会显示多次。我的代码如下: private static readonly object padlock = new object(); private static MyClass _instance =

我正在使用一个共享对象开发一个应用程序,该对象可以通过单例访问。它在32位上工作正常,但在64位上似乎没有正确锁定。在我的对象的构造函数中,我有一些代码,用于检查一些config reg键,并在它们不存在时提示用户。在32位上,我只会像预期的那样看到一次提示,但在64位上,提示会显示多次。我的代码如下:

    private static readonly object padlock = new object();
    private static MyClass _instance = null;
    public static MyClass Instance
    {
        get
        {

            lock (padlock)
            {
                if (_instance == null)
                {
                    _instance = new MyClass();
                }
            }
            return _instance;
        }
    }
非常感谢您的任何意见

编辑以包含示例用法:

    public OtherObject()
    {
        InitializeComponent();

        MyClass.Instance.OtherObjectOrSomething = this;

        this.Load += new System.EventHandler<EventArgs>(OtherObject_Load);
    }
public-OtherObject()
{
初始化组件();
MyClass.Instance.OtherObjectOrSomething=this;
this.Load+=new System.EventHandler(OtherObject\u Load);
}
再次编辑 这是在办公室内运行的AddIn。因此,咬合度取决于办公室的安装。我定义了一个私有的无参数构造函数

谢谢

删除了略微匿名的构造函数

编辑: 基于一些答案和评论,我将回到我最初的答案

我也这样做过,只是我想把readonly改为volatile

private static volatile object padlock = new object();

volatile关键字让编译器知道不要优化指令,这将确保字段中存在最新的值。

有关各种单例实现模式问题的精彩讨论,请参阅(摘自Jon Skeet)

正如所写的,您遇到的最大问题是编译器提供了一个默认的无参数构造函数,它将是公共的。您应该显式创建一个私有的无参数contstructor来防止这种情况。我没有看到任何看起来会导致基于平台架构的问题的东西

以下是我通常使用的代码(在32位和64位系统上):


它可能是构造函数中代码的内部内容,导致多个提示。注册表的视图将不同于32位进程和64位进程,因此它们可以响应不同的外部条件

我提出了一个实现,但由于某些原因,它两次被否决:(

您的单例将您限制为每个应用程序域一个实例。是否有可能在多个应用程序域中创建多个实例?您可以研究一下

在我的对象的构造函数中,我有一些代码,用于检查某些配置注册表项,并在它们不存在时提示用户。

在延迟加载的静态实例中,这是一件相当危险的事情。您能保证UI线程始终是第一个执行此代码路径的线程吗?我不确定这是否是您的问题的一部分,但在线程安全代码中与UI交互很少是一个好主意,我也见过各种奇怪的事情发生n因此不同的环境


你能把这个UI代码移到延迟加载之外吗?如果这是一个Office插件,那么你应该有一个
启动
事件来钩住它,它保证只执行一次。你甚至不需要锁定代码,这样你就可以确保它在任何其他线程尝试触摸它之前被初始化。

我不是故意粗鲁,所以请不要这样认为,但这无助于回答问题。OP的单例实现是可以接受的;它正确、线程安全且简单(只要无参数构造函数标记为
private
)。性能会受到影响,因为每次请求实例时都会使用
锁,但不管怎样。添加
volatile
在这里没有任何用处。让我们重点了解问题所在。@Jason我不是说volatile会解决问题,所以我会删除它,但你是说我所说的帖子吗关于上述方法在某些特定的多处理器机器上失败,nked to是不正确的吗?博客tho有一个主要的dif。锁定围绕if,这是本文的重点。锁定前if的问题是,在任何其他锁定同步根之前,多个线程可能同时命中if。在上述ca中se:这不是问题所在case@David格拉斯:首先,问题是32位机器与64位机器,而不是多处理器机器。如果这个问题是真的,很可能是CLR/抖动问题。其次,该博客上的实现与OP上的实现非常不同;双检查锁定实现是h所熟知的ave问题。再一次,我必须强调OP的实现是正确的。它不是最好的,但它是正确的。我当然不同意我的实现。这通常是我做单例很长一段时间的方式,但我似乎有其他各种实现。如果使用嵌套类可以解决这个问题在我看来,这是一个可以接受的答案。无参数构造函数是否标记为
private
?请显示用于使用singleton实例的代码片段。在帖子中添加了一个片段。我从大量不同的位置访问此对象,但在每个实例中,我都使用MyObject.instance for access.这是否只在VS内部发生?要处理监视器异常,首先要从“监视和调试”窗口中删除对相应类(实例)的所有引用。VS有时喜欢以自己的方式进行操作(也会绕过锁)..@Jason:如图所示的代码将获得编译器提供的默认无参数构造函数,该构造函数将是公共的。@Scott Dorman:首先,我们只得到一个片段,因此您不知道没有显式无参数构造函数。其次,默认无参数构造函数是
public
,而不是
private
就正确性而言,这是一个巨大的差异;前者对于单个词来说是错误的
public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new object();

   private Singleton()
   {
      // any code that needs to run to create a valid instance of the object.
   }

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

         return instance;
      }
   }
}