python 单例模式实现多线程共享链接池

     咱们常常使用数据库链接池,但那是有时候有些库并无实现线程安全的链接池,这个时候,该如何本身封装?多进程和多线程甚至协程模式下,如何控制数据库链接数量或者是socket链接数。这个问题颇有意义。python

该文章后续仍在不断的更新修改中, 请移步到原文地址http://dmwan.ccredis

    首先,多进程,一般的作法是每一个进程实例化一个链接池,为何不共享一个池,由于多进程和多线程同步的开销不同,通常三方库都不会支持,可是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为何线程可以共享一个链接池。bash

下面是打印结果:多线程

instance is 140442806348048
print thread
proc 1 
db1 is  140442806366352proc 2 

db2 is 140442806366352

    看到结果,其实不少问题就知道答案了,使用装饰器后, 整个代码段加载的时候,装饰器就已经开始执行,这里的instances 是不会释放的,实际上代码初始化的时候就执行了DB = singleton(DB) ,至关因而 这个闭包是全局变量,又由于dict自己线程安全。因此每次线程用这闭包的时候,获取链接对象都是线程安全的。闭包

    这里的单例对多进程是不会生效的。   socket

相关文章
相关标签/搜索