详解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中列表、字典、元组、集合数据结构整理
Nov 20 Python
在Python中处理时间之clock()方法的使用
May 22 Python
Python 中urls.py:URL dispatcher(路由配置文件)详解
Mar 24 Python
解决python文件字符串转列表时遇到空行的问题
Jul 09 Python
python 列表,数组和矩阵sum的用法及区别介绍
Jun 28 Python
Python 中的lambda函数介绍
Oct 10 Python
Python自定义一个异常类的方法
Jun 27 Python
python opencv根据颜色进行目标检测的方法示例
Jan 15 Python
django实现更改数据库某个字段以及字段段内数据
Mar 31 Python
Matplotlib自定义坐标轴刻度的实现示例
Jun 18 Python
python切割图片的示例
Nov 12 Python
python 使用openpyxl读取excel数据
Feb 18 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
PHP中的命名空间相关概念浅析
2015/01/22 PHP
php实现JWT验证的实例教程
2020/11/26 PHP
DOMAssitant最新版 DOMAssistant 2.5发布
2007/12/25 Javascript
Zero Clipboard js+swf实现的复制功能使用方法
2010/03/07 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
2013/10/14 Javascript
js获取form的方法
2015/05/06 Javascript
JavaScript实现带标题的图片轮播特效
2015/05/20 Javascript
js中substring和substr两者区别和使用方法
2015/11/09 Javascript
JavaScript中的原型prototype完全解析
2016/05/10 Javascript
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
2016/05/12 Javascript
jQuery插件easyUI实现通过JS显示Dialog的方法
2016/09/16 Javascript
微信小程序开发之实现选项卡(窗口顶部TabBar)页面切换
2016/11/25 Javascript
基于 Vue 的树形选择组件的示例代码
2017/08/18 Javascript
手把手教你用Node.js爬虫爬取网站数据的方法
2018/07/05 Javascript
Vue 表情包输入组件的实现代码
2019/01/21 Javascript
CKEditor扩展插件:自动排版功能autoformat插件实现方法详解
2020/02/06 Javascript
python简单获取数组元素个数的方法
2015/07/13 Python
Python3中在Anaconda环境下安装basemap包
2018/10/21 Python
Python argparse模块使用方法解析
2020/02/20 Python
pytorch Dataset,DataLoader产生自定义的训练数据案例
2021/03/03 Python
使用HTML5和CSS3表单验证功能
2017/05/05 HTML / CSS
纯HTML5+CSS3制作生日蛋糕代码
2016/11/16 HTML / CSS
使用canvas压缩图片大小的方法示例
2019/08/02 HTML / CSS
英国知名奢侈品包包品牌:Milli Millu
2016/12/22 全球购物
Priority Pass机场贵宾室会籍计划:全球超过1200间机场贵宾室
2018/08/26 全球购物
美国便宜的横幅和标志印刷在线:Best of Signs
2019/05/29 全球购物
小蚁科技官方商店:YI Technology
2019/08/23 全球购物
敬老文明号事迹材料
2014/01/16 职场文书
研发工程师岗位职责
2014/04/28 职场文书
自愿离婚协议书范文2014
2014/10/12 职场文书
2014年导购员工作总结
2014/11/18 职场文书
企业2014年度工作总结
2014/12/10 职场文书
python使用XPath解析数据爬取起点小说网数据
2021/04/22 Python
golang import自定义包方式
2021/04/29 Golang
JavaScript事件的委托(代理)的用法示例详解
2022/02/18 Javascript
Vue+TypeScript中处理computed方式
2022/04/02 Vue.js