我一直在做一些主要的设计模式阅读和主题SINGLETONS正在困扰我的HELL。在基本OOP中,我们了解到STATIC变量是CLASS级变量,因此基本上只能有一个实例。
现在,单例的基本实现旨在返回一个STATIC变量,该变量包含自己类的新对象,并且只实例化一次。
class MyClass {
public static MyClass initVar;
private MyClass (){}
public static getInstance (){
if(initVar == null){
initVar = new MyClass();
}
return initVar;
}
}
在用于使用JVM解释此示例的示例中,据说在多线程系统中,如果 getInstance 变量未成为线程,则可以初始化此类的多个实例在方法名称之前使用 synchronize 指令是安全的,所以这就是我的困惑和我的问题。
示例......
var MyClass a = MyClass.getInstance(); //non thread-safe
现在从示例中可以看出,这种非线程安全的实现可以导致MyClass变量 intVar 的MULTIPLE实例,这些实例早先声明为STATIC。我们怎样才能让ONE CLASS返回多个STATIC变量?
即使调用创建多个MyClass对象,也不应该 intVar 仍然只是简单地指向在其上创建的最新MyClass对象,因此我们仍然应该有一个CLASS INSTANCE,最后一个创建了哪个 intVar 现在指向?
对于每个非线程安全的调用,我们实际上可以有多个STATIC变量吗?
MyClass.getInstance()
?
这怎么可能?
答案 0 :(得分:1)
以下是单身人士应该如何实施的方式:
class MyClass {
public static final MyClass initVar = new MyClass();
private MyClass (){}
public static MyClass getInstance (){
return initVar;
}
}
完全线程安全。
您不会在Singleton中包含有关可变状态的任何信息。如果您添加任何内容,则必须进行同步。
在你所有的研究之后,你会发现,如果今天写了GoF书,那么Singleton将会被选出岛外。 Google进入great deal of trouble以取消Singletons。
答案 1 :(得分:1)
多线程访问单例的问题是所谓的“竞争条件”问题不在于它会返回不同的实例。问题是当多个线程试图同时访问相同的数据时。您需要同步保护数据,因此在给定时间只有一个线程访问您的单例。
我用于单身的一种技术是使用'懒惰实例化':
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;
}
}