单例的使用

在iOS里面有很多使用单例的地方,比如NSUserDefault,NotificationCenter等。如果我们自己要使用单例模式的话,应该怎么办呢?

会造成非单例的构造方法:

单例1

这种创建方法,在多线程情况下会出错,如下图所示:

多线程

打印出如下两个图所示,有时候确实是单例,但有时候却是不同的两个实例:

多线程下的单例4

多线程下的单例3

究竟是在哪里出了问题呢?%>_<%,如下图所示,假如两个线程同时去判断single是不是nil,而此时必然是nil,则都会去生成相应的对象。

pic singtle

解决办法:

方法一、给获取单例那段代码加上 @symchronized(self)修饰符,则同一时间只能有一个线程访问这段代码

多线程下的单例5

方法二、使用GCD

GCD

避免滥用单例

单例确实很方便,但是也会有很纠结的一面。比如说,写测试的时候 T^T,测试里面的很多方法并不是按照你写的顺序执行的,但是在实际应用中你的代码是有顺序的,这就给我们带来了麻烦。

为了让测试顺利通过,只能在setup里面获取单例,且在tearDown里面让sharedInstance = nil

另外,关闭一个单例也基本是很难做到的,只有当程序所占的内存被收回的时候,单例才能被释放。如果是那种可以切换账号登录的,则应该小心使用单例。

参考

1.avoid singleton abuse

2.singleton in objective-c