python中单例模式介绍(含线程安全的单例模式)

devtools/2025/3/3 14:58:52/

理解单例模式之前,确实需要先掌握 __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 = Nonedef __new__(cls, *args, **kwargs):print("__new__")if not cls._instance:cls._instance = super().__new__(cls)return cls._instancedef __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 threadingclass 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


http://www.ppmy.cn/devtools/164209.html

相关文章

Qt 文件操作+多线程+网络

文章目录 1. 文件操作1.1 API1.2 例子1,简单记事本1.3 例子2,输出文件的属性 2. Qt 多线程2.1 常用API2.2 例子1,自定义定时器 3. 线程安全3.1 互斥锁3.2 条件变量 4. 网络编程4.1 UDP Socket4.2 UDP Server4.3 UDP Client4.4 TCP Socket4.5 …

EMO模型详解及代码复现

EMO定义 EMO(Efficient Mobile Networks)是一种 面向移动端的轻量化网络模型 ,旨在 在参数、FLOPs和性能之间实现平衡 ,特别适用于 密集预测任务 。EMO的设计理念源于对CNN和Transformer架构的深入理解,通过整合两者的优势,实现了高效的模型性能。 EMO的核心是 反向残差…

【北京迅为】itop-3568 开发板openharmony鸿蒙烧写及测试-第2章OpenHarmony v3.2-Beta4版本测试

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…

playwright 自动化登录验证码,测试Iframe

还记得之前的文章吗,我们之前有说过,实现自动登录,详细分析了Playwright实战中登录状态问题。下面聚焦到storageState从原理到实战实现登录状态管理,从而一劳永逸解决验证码问题。 简介:在自动化测试中,频…

C++ ++++++++++

初始C 注释 变量 常量 关键字 标识符命名规则 数据类型 C规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存 整型 sizeof关键字 浮点型(实型) 有效位数保留七位,带小数点。 这个是保…

webstorm的Live Edit插件配合chrome扩展程序JetBrains IDE Support实现实时预览html效果

前言 我们平时在前端网页修改好代码要点击刷新再去看修改的效果,这样比较麻烦,那么很多软件都提供了实时预览的功能,我们一边编辑代码一边可以看到效果。下面说的是webstorm。 1 Live Edit 首先我们需要在webstorm的settings里安装插件Live …

Elasticsearch:过滤 HNSW 搜索,快速模式

作者:来自 Elastic Benjamin Trent 通过我们的 ACORN-1 算法实现,探索我们对 Apache Lucene 中的 HNSW 向量搜索所做的改进。 多年来,Apache Lucene 和 Elasticsearch 一直支持使用 kNN 查询的过滤搜索,允许用户检索符合指定元数据…

【开源】低代码 C++程序框架,Linux多线程程序

大家好,欢迎来到停止重构的频道。 本期介绍我们新的C低代码框架:Bees,用于编写Linux/Unix的多线程程序。 低代码框架一般是不会对C程序下手的,因为C程序一般是比较复杂的程序,光是多线程同步就够头疼的了。 但是我们…