简体   繁体   English

设计模式:单例混淆

[英]Design Patterns: The Singleton confusion

I have been doing some major design patterns reading and the subject SINGLETONS is bugging me the HELL out. 我一直在阅读一些主要的设计模式,而主题SINGLETONS正在使我烦恼。 In basic OOP we learn that STATIC variables are CLASS level variables and thus can basically only have ONE INSTANCE. 在基本的OOP中,我们了解到STATIC变量是CLASS级别的变量,因此基本上只能具有一个实例。

Now the basic implementation of a singleton is intended to return a STATIC variable which holds a new object of its own class and which is instantiated only once. 现在,单例的基本实现旨在返回一个STATIC变量,该变量持有其自己类的新对象,并且仅实例化一次。

class MyClass {
      public static MyClass initVar;

      private MyClass (){}

      public static getInstance (){
           if(initVar == null){
              initVar = new MyClass();
           }
           return initVar;
      }

}

In the example that was being used to explain this using JVM, it was said that in a multithreaded system more than one instance of this class can be initialized if the getInstance variable isn't made thread safe by using the synchronize directive before the method name, so here in lies my confusion and my question. 在用于使用JVM进行解释的示例中,据说在多线程系统中,如果在方法名称前使用syncize指令未使getInstance变量成为线程安全的,则可以初始化该类的多个实例。 ,这就是我的困惑和问题所在。

the example... 这个例子...

var MyClass a = MyClass.getInstance(); //non thread-safe

now from the example it is said that this non thread-safe implementation can lead to MULTIPLE instances of the MyClass variable intVar that was earlier on declared STATIC. 现在从该示例中可以说,这种非线程安全的实现可以导致MyClass变量intVar的多个实例,该实例早于声明的STATIC。 How can we have multiple STATIC variables being returned by ONE CLASS? 我们如何通过一个类返回多个STATIC变量?

Even if the call creates multiple MyClass objects, shouldn't intVar still just simply point to the newest MyClass object that was created on it and thus we should still have ONE CLASS INSTANCE, the last one created which intVar is now pointing to? 即使调用创建了多个MyClass对象, intVar也不应该仅指向创建于其上的最新MyClass对象,因此我们仍应具有ONE CLASS INSTANCE,即intVar现在指向的最后一个实例?

Can we actually have multiple STATIC variables for every non thread-safe call on MyClass.getInstance() ? 对于MyClass.getInstance()上的每个非线程安全调用,我们实际上可以有多个STATIC变量吗?

How can this be? 怎么会这样?

Here's how a Singleton ought to be implemented: 以下是应实现Singleton的方式:

class MyClass {
      public static final MyClass initVar = new MyClass();

      private MyClass (){}

      public static MyClass getInstance (){
           return initVar;
      }
}

Perfectly thread safe. 完全线程安全。

You don't include any information about mutable state in your Singleton. 您在Singleton中不包含有关可变状态的任何信息。 If you add any, you'll have to synchronize. 如果添加任何内容,则必须进行同步。

You realize, after all your research, that Singleton would be voted off the island if the GoF book was written today. 在进行了所有研究之后,您意识到,如果今天写的是GoF书,那么Singleton将会被选为孤岛。 Google goes to a great deal of trouble to root out Singletons. Google根除Singleton 的麻烦很大

The problem with multithreaded access to a singleton is what is called a 'race condition' The problem is not that it will return different instances. 多线程访问单例的问题是所谓的“竞赛条件”,问题不在于它将返回不同的实例。 The problem is when multiple threads try to access the same data at the same time. 问题是当多个线程尝试同时访问相同的数据时。 You need to sync protect the data, so only one thread is accessing your singleton at a given time. 您需要同步保护数据,因此在给定时间只有一个线程正在访问您的单例。

One technique I use for singletons is using 'lazy instantiation': 我用于单例的一种技术是使用“延迟实例化”:

class MyClass{
public static final MyClass initVar = 0;

public static MyClass getInstance(){
     if (self.initVar == 0){
         // -> Lazy instantiation, this should only happen once. 
         // You can add some assert code here to verify that this is only 
         // happening once in your application. With lazy instantiation you 
         // wait until you actually need the object to create it.
         self.initVar = new MyClass();   
     }

     return initVar;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM