单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
来看看tornado.IOLoop
中的单例模式:
为什么这里要double check
?
简单的单例模式
先来看看代码:
在 Python 里,可以在真正的构造函数__new__
里做文章:
这种情况看似还不错,但是不能保证在多线程的环境下仍然好用,看图:
出现了多线程之后,这明显就是行不通的。
上锁使线程同步
上锁后的代码:
这里确实是解决了多线程的情况,但是我们只有实例化的时候需要上锁,其它时候Singleton._instance
已经存在了,不需要锁了,但是这时候其它要获得Singleton
实例的线程还是必须等待,锁的存在明显降低了效率,有性能损耗。
全局变量
在 Java/C++ 这些语言里还可以利用全局变量的方式解决上面那种加锁(同步)带来的问题:
在 Python 里就是这样了:
但是如果这个类所占的资源较多的话,还没有用这个实例就已经存在了,是非常不划算的,Python 代码也略显丑陋……
总结
所以出现了像tornado.IOLoop.instance()
那样的double check
的单例模式了。在多线程的情况下,既没有同步(加锁)带来的性能下降,也没有全局变量直接实例化带来的资源浪费。
6-25 补充(使用 decorator):
https://wiki.python.org/moin/PythonDecoratorLibrary#Singleton
https://wiki.python.org/moin/PythonDecoratorLibrary#The_Sublime_Singleton
8-27 更:
我认为政治正确的单例模式,见:singleton.py