程序员历来不缺对象,想 new
几个就 new
几个。程序员
可是对象多了不免会出点问题,指不定哪天哪一个对象就爆炸了。单例模式就是为了解决这个问题,不管 new
了几回,都只能存在一个对象,相似一些网站的登陆,就是经过这种方式,实现只能有一个帐号登陆之类的功能。安全
首先能够简单地实现一下:网站
class Singleton(object): __instance = None def __init__(self, *args, **kwargs): pass @classmethod def get_instance(cls, *args, **kwargs): if not cls.__instance: cls.__instance = Singleton(*args, **kwargs) return cls.__instance obj1 = Singleton.get_instance() obj2 = Singleton.get_instance() print(obj1) print(obj2)
输出以下,能够看出两个对象 obj1
和 obj2
是同一个地址,即这个时候只有一个对象。spa
<__main__.Singleton object at 0x0000015F47A2CC88> <__main__.Singleton object at 0x0000015F47A2CC88>
但这种方法不是线程安全的:线程
import threading import time class Singleton(object): __instance = None def __init__(self, *args, **kwargs): time.sleep(1) @classmethod def get_instance(cls, *args, **kwargs): if not cls.__instance: cls.__instance = Singleton(*args, **kwargs) return cls.__instance def task(): obj = Singleton.get_instance() print(obj) for i in range(6): threading.Thread(target=task).start()
输出结果,出现了多个对象:code
<__main__.Singleton object at 0x0000028A133F1F48> <__main__.Singleton object at 0x0000028A134C93C8> <__main__.Singleton object at 0x0000028A134C9288> <__main__.Singleton object at 0x0000028A134C9148> <__main__.Singleton object at 0x0000028A134BEFC8> <__main__.Singleton object at 0x0000028A134C9508>
并且上面这种方法只有第一次 get_instance()
的时候能给对象传递参数,总之有许多弊端。Python
提供了 __new__
方法正好完美解决了这个问题,再加上锁,就能实现一个线程安全的单例模式:对象
import threading import time class Singleton(object): __lock = threading.Lock() __instance = None def __new__(cls, *args, **kwargs): with cls.__lock: if not cls.__instance: cls.__instance = super().__new__(cls) return cls.__instance def __init__(self, *args, **kwargs): time.sleep(1) def task(): obj = Singleton() print(obj) if __name__ == '__main__': for i in range(6): threading.Thread(target=task).start()
输出结果:blog
<__main__.Singleton object at 0x000001DA4A1C0F88> <__main__.Singleton object at 0x000001DA4A1C0F88> <__main__.Singleton object at 0x000001DA4A1C0F88> <__main__.Singleton object at 0x000001DA4A1C0F88> <__main__.Singleton object at 0x000001DA4A1C0F88> <__main__.Singleton object at 0x000001DA4A1C0F88>