ToB企服应用市场:ToB评测及商务社交产业平台
标题:
python中单例模式先容(含线程安全的单例模式)
[打印本页]
作者:
大连密封材料
时间:
5 天前
标题:
python中单例模式先容(含线程安全的单例模式)
理解单例模式之前,确实必要先掌握 __init__、__new__ 和 __call__ 这三个方法的作用和调用序次。如有必要,读者可跳转下方链接学习:
python中的__init__、__new__、__call__-CSDN博客
正文开始:
在Python中,单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点。
一、利用装饰器实现单例
原理
:通过装饰器控制类的实例化过程,确保仅天生一个实例。
步骤
:
1. 界说一个装饰器函数。
2. 在装饰器中管理实例的创建和返回。
代码示例
:
def singleton_decorator(cls):
print("装饰器执行(类定义时立即执行)")
instances = {}
def get_instance(*args, **kwargs):
print("调用 get_instance()(实例化时执行)")
if cls not in instances: # 单例模式的关键点就在这里
print("创建新实例")
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton_decorator
class SingletonClass:
def __init__(self):
print("调用 __init__()")
self.data = "Singleton Data"
# 测试
print("开始实例化")
a = SingletonClass()
print("------------")
b = SingletonClass()
print(a is b) # 输出:True
# 装饰器执行(类定义时立即执行)
# 开始实例化
# 调用 get_instance()(实例化时执行)
# 创建新实例
# 调用 __init__()
# ------------
# 调用 get_instance()(实例化时执行)
# True
复制代码
二、元类实现单例重写__call__
原理
:通过元类的 __call__ 方法控制实例创建流程。
步骤
:
1. 界说一个元类,重写 __call__ 方法。
2. 在元类中查抄是否已存在实例。
代码示例
:
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
print("调用 __call__()")
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class SingletonClass(metaclass=SingletonMeta):
def __init__(self):
print("调用 __init__()")
self.data = "Singleton Data"
# 测试
a = SingletonClass()
b = SingletonClass()
print(a is b) # 输出:True
# 调用 __call__()
# 调用 __init__()
# 调用 __call__()
# True
复制代码
三、重写 __new__
原理
:通过重写类的 __new__ 方法,直接控制实例创建。
步骤
:
1. 在类中界说类变量存储实例。
2.在 __new__ 方法中返回已有实例或创建新实例。
代码示例
:
class SingletonClass:
_instance = None
def __new__(cls, *args, **kwargs):
print("__new__")
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
print("__init__")
self.data = "Singleton Data"
# 测试
a = SingletonClass()
b = SingletonClass()
print(a is b) # 输出:True
# __new__
# __init__
# __new__
# __init__
# True
复制代码
四、线程安全的单例模式
问题
:上述方法在并发环境下大概创建多个实例。
解决方案
:加锁(如 threading.Lock)确保线程安全。
代码示例(元类 + 线程安全)
:
import threading
class SingletonMeta(type):
"""
单例模式的元类实现。
控制类的实例化过程,确保线程安全且唯一实例。
"""
_instances = {} # 保存所有单例类的实例(键是类,值是实例)
_lock = threading.Lock() # 线程锁
def __call__(cls, *args, **kwargs):
# 第一次检查:避免已存在实例时不必要的加锁
if cls not in cls._instances:
# 加锁确保线程安全
with cls._lock:
# 第二次检查:防止其他线程已创建实例
if cls not in cls._instances:
# 创建实例并保存
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
# 返回已存在的实例
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
"""
单例类示例。
通过元类 SingletonMeta 控制实例唯一性。
"""
def __init__(self):
# 初始化代码(只会执行一次)
self._data = "单例数据"
print("Singleton 初始化完成")
# 测试多线程环境下的单例行为
def create_singleton():
obj = Singleton()
print(id(obj))
if __name__ == "__main__":
threads = []
for _ in range(5):
t = threading.Thread(target=create_singleton)
threads.append(t)
t.start()
for t in threads:
t.join()
# Singleton 初始化完成
# 1807031580512
# 1807031580512
# 1807031580512
# 1807031580512
# 1807031580512
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4