程序員歷來不缺對象,想 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>