安全与不安全的单例模式
前几天在android开发中做了一个loginHelper的单例。(不考虑多进程的情况)
在初始化loginHelper单例时。做的一些初始化工作出现了问题。
出问题的初始化工作:
首先随机产生了rsa秘钥对。然后想把这个秘钥对保存在SharedPreference中。
不论android的SharedPreference还是android的NSUserDefaults都是来存储
用户对程序进行的一些偏好设置。在文件系统都是xml文件。
错误表现:
程序保存在xml文件中的秘钥对与程序产生的秘钥对,不吻合。
分析问题:
顿时,我在想为啥在单例模式下还出现了这个问题呢,最后发现,原来我用的
单例模式的方法不是线程安全的。
我用的实现单例的方式:
static LoginHelper instance = null;
LoginHelper getInstance()
{
if(instance !=null){
instance = new LoginHelper();
}
return instance;
}
通过上面的方式实现单例是不安全的。由于写文件的时间比较长,很有可能两个线程都会实例化LoginHelper。
后面换了一种方式实现单例模式:
private final static LoginHelper instance = new LoginHelper();
LoginHelper getInstance()
{
return instance;
}
其实我们也可以通过代码块加锁的形式来防止多线程问题
static LoginHelper instance = null;
LoginHelper getInstance()
{
synchronized(this){
if(instance!=null){
instance = new LoginHelper();
}
return instance;
}
}
由于是final格式的类静态成员,只会在类加载的时候初始化,所以保证instance只会被实例化一次,后面不会被修改。。
其实ios通过gcd技术提供了一种线程安全单例模式实现。
+ (id)sharedInstance
{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}