详解python实现线程安全的单例模式


Posted in Python onMarch 05, 2018

单例模式是一种常见的设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,服务器的配置信息写在一个文件中online.conf中,客户端通过一个 Config 的类来读取配置文件的内容。如果在程序运行期间,有很多地方都需要使用配置文件的内容,那么每个调用配置文件的地方都会创建 Config的实例,这就导致系统中存在多个Config 的实例对象,在配置文件内容很多的情况下,我们就浪费了大量的内存做了同样的事。事实上,对于Config类我们在程序运行期间时只需要一个实例对象即可,这时单例模式就是最好的选择。

python的模块就是天然的单例模式,这里我们使用修饰器来实现单例模式,以下是代码实现

def Singleton(cls):
 instances = {}

 def get_instance(*args, **kw):
  if cls not in instances:
   instances[cls] = cls(*args, **kw)
  return instances[cls]

 return get_instance

代码也很简单,将类传入单例修饰器中,如果该类还未生成实例(instances中不存在该类),那么就生成一个新的实例返回,并记录在instances中。如果已经instances中已经存在该类,那么直接返回实例instances[cls]。

那么这段代码是完美的吗?答案是否定的,这段代码不是线程安全的。要实现线程安全需要配合锁的使用,只有占有锁的线程才能继续访问单例实例,看来我们需要再写一个修饰器来实现线程安全了,以下是完整的代码实现和简单的多线程测试用例。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import threading

def synchronized(func):
 func.__lock__ = threading.Lock()

 def synced_func(*args, **kws):
  with func.__lock__:
   return func(*args, **kws)

 return synced_func

def Singleton(cls):
 instances = {}

 @synchronized
 def get_instance(*args, **kw):
  if cls not in instances:
   instances[cls] = cls(*args, **kw)
  return instances[cls]

 return get_instance

def worker():
 single_test = test()
 print "id----> %s" % id(single_test)

@Singleton
class test():
 a = 1
if __name__ == "__main__":
 task_list = []
 for one in range(30):
  t = threading.Thread(target=worker)
  task_list.append(t)
 for one in task_list:
  one.start()
 for one in task_list:
  one.join()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python解析xml文件操作实例
Oct 05 Python
Python判断Abundant Number的方法
Jun 15 Python
总结网络IO模型与select模型的Python实例讲解
Jun 27 Python
python 开发的三种运行模式详细介绍
Jan 18 Python
ubuntu安装sublime3并配置python3环境的方法
Mar 15 Python
python pandas 如何替换某列的一个值
Jun 09 Python
python中ImageTk.PhotoImage()不显示图片却不报错问题解决
Dec 06 Python
pycharm中使用anaconda部署python环境的方法步骤
Dec 19 Python
python flask解析json数据不完整的解决方法
May 26 Python
为什么从Python 3.6开始字典有序并效率更高
Jul 15 Python
python求numpy中array按列非零元素的平均值案例
Jun 08 Python
PyTorch device与cuda.device用法
Apr 03 Python
分析python动态规划的递归、非递归实现
Mar 04 #Python
python3.x上post发送json数据
Mar 04 #Python
python数据封装json格式数据
Mar 04 #Python
Python爬虫实例扒取2345天气预报
Mar 04 #Python
Python爬虫设置代理IP的方法(爬虫技巧)
Mar 04 #Python
浅析python实现scrapy定时执行爬虫
Mar 04 #Python
Python使用Scrapy爬虫框架全站爬取图片并保存本地的实现代码
Mar 04 #Python
You might like
深入for,while,foreach遍历时间比较的详解
2013/06/08 PHP
php中PDO方式实现数据库的增删改查
2015/05/17 PHP
JavaScript 读取元素的CSS信息的代码
2010/02/07 Javascript
基于jQuery的消息提示插件 DivAlert之旅(二)
2010/04/01 Javascript
JS中产生20位随机数以0-9为例也可以是a-z A-Z
2014/08/01 Javascript
JS+DIV实现鼠标划过切换层效果的方法
2015/05/25 Javascript
js判断主流浏览器类型和版本号的简单实现代码
2016/05/26 Javascript
微信js-sdk地理位置接口用法示例
2016/10/12 Javascript
JavaScript实现的冒泡排序法及统计相邻数交换次数示例
2017/04/26 Javascript
浅谈js使用in和hasOwnProperty获取对象属性的区别
2017/04/27 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
2018/08/19 Javascript
面试题:react和vue的区别分析
2019/04/08 Javascript
vscode中的vue项目报错Property ‘xxx‘ does not exist on type ‘CombinedVueInstance<{ readyOnly...Vetur(2339)
2020/09/11 Javascript
[55:44]OG vs NAVI 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
举例介绍Python中的25个隐藏特性
2015/03/30 Python
Python装饰器原理与用法分析
2018/04/30 Python
Pandas之ReIndex重新索引的实现
2019/06/25 Python
python SocketServer源码深入解读
2019/09/17 Python
从训练好的tensorflow模型中打印训练变量实例
2020/01/20 Python
解决Python3.8用pip安装turtle-0.0.2出现错误问题
2020/02/11 Python
python实现输入三角形边长自动作图求面积案例
2020/04/12 Python
详解pyinstaller生成exe的闪退问题解决方案
2020/06/19 Python
Python中三维坐标空间绘制的实现
2020/09/22 Python
html5构建触屏网站之网站尺寸探讨
2013/01/07 HTML / CSS
Sneaker Studio乌克兰:购买运动鞋
2018/03/26 全球购物
ECHT官方网站:男女健身服
2020/02/14 全球购物
Python面试题:如何用Python来发送邮件
2016/03/15 面试题
建筑自我鉴定
2013/10/19 职场文书
业务主管岗位职责
2013/11/20 职场文书
信息服务专业毕业生求职信
2014/03/02 职场文书
社区居务公开实施方案
2014/03/27 职场文书
幼儿园六一儿童节演讲稿
2015/03/19 职场文书
会议主持人开场白台词
2015/05/28 职场文书
党员公开承诺书(2016最新版)
2016/03/24 职场文书
python开发实时可视化仪表盘的示例
2021/05/07 Python
使用Redis实现点赞取消点赞的详细代码
2022/03/20 Redis