使用場景: + Python的logger就是一個單例模式,用以日誌記錄 + Windows的資源管理器是一個單例模式 + 線程池,數據庫鏈接池等資源池通常也用單例模式 + 網站計數器html
從這些使用場景咱們能夠總結下什麼狀況下須要單例模式:python
1. 當每一個實例都會佔用資源,並且實例初始化會影響性能,這個時候就能夠考慮使用單例模式,它給咱們帶來的好處是隻有一個實例佔用資源,而且只需初始化一次; 2. 當有同步須要的時候,能夠經過一個實例來進行同步控制,好比對某個共享文件(如日誌文件)的控制,對計數器的同步控制等,這種狀況下因爲只有一個實例,因此不用擔憂同步問題。
class Singleton(object): __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs) # 能夠在這裏給實力對象綁定一些固有屬性 # cls.__instance.appkey = "" return cls.__instance
class Singleton(object): def __new__(cls, *args, **kwargs): # 判斷是否存在類屬性_instance,_instance是類CCP的惟一對象,即單例 if not hasattr(Singleton, "__instance"): cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs) # cls.__instance = object.__new__(cls) return cls.__instance
可是以上的方法在多線程中會有線程安全問題,當有多個線程同時去初始化對象時,就極可能同時判斷__instance is None,從而進入初始化instance的代碼中(若是有__init__方法)。因此須要用互斥鎖來解決這個問題。數據庫
import threading try: from synchronize import make_synchronized except ImportError: def make_synchronized(func): import threading func.__lock__ = threading.Lock() # 用裝飾器實現同步鎖 def synced_func(*args, **kwargs): with func.__lock__: return func(*args, **kwargs) return synced_func class Singleton(object): __instance = None @make_synchronized def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance def __init__(self): self.blog = "blog" # ------------- def worker(): e = Singleton() print(id(e)) def meta(): e1 = Singleton() e2 = Singleton() e1.blog = 123 print(e1.blog) print(e2.blog) print(id(e1)) print(id(e2)) if __name__ == "__main__": meta() tasks = [threading.Thread(target=worker) for _ in range(20)] for task in tasks: task.start() task.join()
# 裝飾器(decorator)能夠動態地修改一個類或函數的功能 import functools def singleton(cls): __instance = {} @functools.wraps(cls) def getinstance(*args, **kwargs): if cls not in __instance: __instance[cls] = cls(*args, **kwargs) return __instance[cls] return getinstance @singleton class MyClass(object): a = 1
咱們定義了一個裝飾器 singleton,它返回了一個內部函數 getinstance,該函數會判斷某個類是否在字典 instances 中,若是不存在,則會將 cls 做爲 key,cls(*args, **kw) 做爲 value 存到 instances 中,不然,直接返回 instances[cls]。設計模式
class Singleton(type): __instances = {} def __call__(cls, *args, **kwargs): if cls not in cls.__instances:) cls.__instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls.__instances[cls] # python2寫法 # class MyClass(object): # __metaclass__ = Singleton() # python3寫法 class MyClass(metaclass=Singleton): def __init__(self): self.blog = "blog"
參考:
Python 中的單例模式
設計模式(Python)-單例模式安全
原文出處:https://www.cnblogs.com/panlq/p/12355917.html多線程