详解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解释执行原理分析
Aug 22 Python
Python实现根据IP地址和子网掩码算出网段的方法
Jul 30 Python
详解Python3中字符串中的数字提取方法
Jan 14 Python
Ubuntu下创建虚拟独立的Python环境全过程
Feb 10 Python
使用Pyinstaller转换.py文件为.exe可执行程序过程详解
Aug 06 Python
python基础教程之while循环
Aug 14 Python
关于numpy中eye和identity的区别详解
Nov 29 Python
python构造函数init实例方法解析
Jan 19 Python
python数字类型math库原理解析
Mar 02 Python
python爬虫使用scrapy注意事项
Nov 23 Python
python 日志模块logging的使用场景及示例
Jan 04 Python
Python 数据科学 Matplotlib图库详解
Jul 07 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
ThinkPHP V2.2说明文档没有说明的那些事实例小结
2015/07/01 PHP
PHP生成图像验证码的方法小结(2种方法)
2016/07/18 PHP
PHP实现更改hosts文件的方法示例
2017/08/08 PHP
详解PHP神奇又有用的Trait
2019/03/25 PHP
js Dialog 实践分享
2012/10/22 Javascript
深入理解javaScript中的事件驱动
2013/05/21 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
jquery序列化表单以及回调函数的使用示例
2014/07/02 Javascript
jQuery+slidereveal实现的面板滑动侧边展出效果
2015/03/14 Javascript
javascript实现淘宝幻灯片广告展示效果
2015/04/27 Javascript
基于JavaScript实现动态创建表格和增加表格行数
2015/12/20 Javascript
在Html中使用Requirejs进行模块化开发实例详解
2016/04/15 Javascript
js实现人民币大写金额形式转换
2016/04/27 Javascript
jQuery实现的表格展开伸缩效果实例
2016/09/07 Javascript
Express与NodeJs创建服务器的两种方法
2017/02/06 NodeJs
jQuery插件echarts实现的循环生成图效果示例【附demo源码下载】
2017/03/04 Javascript
ES6新数据结构Map功能与用法示例
2017/03/31 Javascript
jQuery Ajax 实现分页 kkpager插件实例代码
2017/08/10 jQuery
Vue中v-for的数据分组实例
2018/03/07 Javascript
NodeJS实现自定义流的方法
2018/08/01 NodeJs
node.js express框架实现文件上传与下载功能实例详解
2019/10/15 Javascript
jQuery操作元素的内容和样式完整实例分析
2020/01/10 jQuery
vue+Element-ui前端实现分页效果
2020/11/15 Javascript
微信 用脚本查看是否被微信好友删除
2016/10/28 Python
你所不知道的Python奇技淫巧13招【实用】
2016/12/14 Python
python批量修改图片大小的方法
2018/07/24 Python
Python基础教程之异常详解
2019/01/10 Python
python实现数据清洗(缺失值与异常值处理)
2019/12/02 Python
室内设计专业个人的自我评价
2013/10/19 职场文书
简历的个人自我评价范文
2014/01/03 职场文书
实习生自我评价
2014/01/18 职场文书
幼儿园优秀班主任事迹材料
2014/05/14 职场文书
销售人员求职信
2014/07/22 职场文书
先进集体申报材料
2014/12/25 职场文书
python opencv旋转图片的使用方法
2021/06/04 Python
WinServer2012搭建DNS服务器的方法步骤
2022/06/10 Servers