使用场景: + 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多线程