python 单例模式实现多线程共享连接池
2017-09-02 00:00
267 查看
我们经常使用数据库连接池,但那是有时候有些库并没有实现线程安全的连接池,这个时候,该如何自己封装?多进程和多线程甚至协程模式下,如何控制数据库连接数量或者是socket连接数。这个问题很有意义。
首先,多进程,通常的做法是每个进程实例化一个连接池,为什么不共享一个池,因为多进程和多线程同步的开销不一样,一般三方库都不会支持,但是redis 的库可以,他有些细节不一样。然后多线程共享,只需要将连接放到一个线程安全的容器,比如list 或者queue中。注意多线程和多进程的queue实现方式完全不一样,多线程是使用的mmap。
下面看看一个demo:
这部分代码是简化了自己封装的连接池的代码, 主要观察线程单例是否生效,然后那个instance为什么线程能够共享一个连接池。
下面是打印结果:
看到结果,其实很多问题就知道答案了,使用装饰器后, 整个代码段加载的时候,装饰器就已经开始执行,这里的instances 是不会释放的,实际上代码初始化的时候就执行了DB = singleton(DB) ,相当于是 这个闭包是全局变量,又因为dict本身线程安全。所以每次线程用这闭包的时候,获取连接对象都是线程安全的。
这里的单例对多进程是不会生效的。
首先,多进程,通常的做法是每个进程实例化一个连接池,为什么不共享一个池,因为多进程和多线程同步的开销不一样,一般三方库都不会支持,但是redis 的库可以,他有些细节不一样。然后多线程共享,只需要将连接放到一个线程安全的容器,比如list 或者queue中。注意多线程和多进程的queue实现方式完全不一样,多线程是使用的mmap。
下面看看一个demo:
import multiprocessing import threading import os def singleton(cls, *args, **kw): instances = {}# print "instance is",id(instances) def _singleton(): #key = str(cls) + str(os.getpid()) key = str(cls) if key not in instances: instances[key] = cls(*args, **kw) return instances[key] return _singleton print "instance has been free" @singleton class DB(object): def __init__(self): self.rabbitmq_pool = self.init_rabbitmq_pool() def init_rabbitmq_pool(self): pool = 1#为了简化 return pool #DB = singleton(DB) def process1(): print "proc 1 " db1 = DB() print "db1 is ", id(db1) def process2(): print "proc 2 " db2 = DB() print "db2 is", id(db2) if __name__=="__main__": # print "multiproce " # pro1 = multiprocessing.Process(target=process1) # pro2 = multiprocessing.Process(target=process2) # pro1.start() # pro2.start() # pro1.join() # pro2.join() print "print thread" pro1 = threading.Thread(target=process1) pro2 = threading.Thread(target=process2) pro1.start() pro2.start() pro1.join() pro2.join()
这部分代码是简化了自己封装的连接池的代码, 主要观察线程单例是否生效,然后那个instance为什么线程能够共享一个连接池。
下面是打印结果:
instance is 140442806348048 print thread proc 1 db1 is 140442806366352proc 2 db2 is 140442806366352
看到结果,其实很多问题就知道答案了,使用装饰器后, 整个代码段加载的时候,装饰器就已经开始执行,这里的instances 是不会释放的,实际上代码初始化的时候就执行了DB = singleton(DB) ,相当于是 这个闭包是全局变量,又因为dict本身线程安全。所以每次线程用这闭包的时候,获取连接对象都是线程安全的。
这里的单例对多进程是不会生效的。
相关文章推荐
- 用python多线程方式实现生产者与消费者模式
- 多线程学习--通过单例模式来实现多个线程中的数据共享
- 『Python』 多线程 共享变量的实现
- 观察者模式 python实现
- 在Forms验证模式下,实现多个站点(SubDomain相同)共享同一用户登录状态
- <读书笔记> Thinking in python (Python 设计模式) 1. Singlton的c++与python的实现
- 多线程安全的单件模式,模板基类的单件实现
- 虚拟拨号上网模式下实现双机共享上网的一种最省钱的方法
- 【转载】多线程--C#利用多线程实现消费者和生产者模式
- 用Python的类变量实现单一模式
- 多线程---使用ManualResetEvent来控制线程间的同步(实现了消费者和生产者模式)
- Head First 设计模式——观察者模式(Observer Pattern)——Python实现(2)
- Head First 设计模式——策略模式(Strategy Pattern)——Python实现
- Head First 设计模式——观察者模式(Observer Pattern)——Python实现(3)
- 多线程间实现数据共享(传递)方法
- 双机热备的实现模式 - 基于共享存储与纯软件方式
- MapServer实现数据互操作与Web共享模式
- python 多线程 XML RPC的实现
- 多线程---使用ManualResetEvent来控制线程间的同步(实现了消费者和生产者模式)
- 在Forms验证模式下,实现多个站点(SubDomain相同)共享同一用户登录状态