python多线程下保持单例模式的实例唯一

先描述在python中的一个场景,我有个自定义的类,实例了一些transfer信息传递及线程池的作用,然后还需要被用来共享一些服务配置。 这时候稍不注意会出现一批新的类实例被创建。 这样造成了数据不能共享,浪费资源。 我知道大家也不想这样,但往往不注意就这样了。 肿么办?  可以直接上单例模式!

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。http://xiaorui.cc/?p=3165

那么什么是单例模式? 

简单说单例模式可以保证一个类仅有一个实例, 并提供一个访问它的全局访问点——《设计模式》, 再废话一句,单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。


– 特点

    – 单例类只能有一个实例或给定数目的单例
    – 单例类必须给所有其他对象提供这个实例

– 优点
    – 避免对资源的多重占用,避免对同一个资源文件的同时操作,造成文件状态不一致
    – 减少内存开支,尤其是需要频繁创建和使用的类
    – 设置全局访问点,优化和共享资源访问

– 场景
    – 减少在协同开发中产生类似的实例对象,节省资源
    – 整个项目中需要一个共享访问带点或共享数据

.

这里不相信讲解代码了,实现很是简单,借用类变量做个标记,首先使用__new__创建实例对象。 如果你再次创建一个实例对象的时候,首先会在cls.instance判断是否已经创建过实例对象.这样就能防止实例被多次创建。  多线程的环境实现起来也简单,加了一个threading lock同步锁而已。 

#xiaorui.cc
import threading
try:
    from synchronize import make_synchronized
except ImportError:
    def make_synchronized(func):
        import threading
        func.__lock__ = threading.Lock()

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

        return synced_func

class Singleton(object):
    instance = None

    @make_synchronized
    def __new__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = object.__new__(cls, *args, **kwargs)
        return cls.instance

    def __init__(self):
        self.blog = "xiaorui.cc"

    def go(self):
        pass

def worker():
    e = Singleton()
    print id(e)
    e.go()

def test():
    e1 = Singleton()
    e2 = Singleton()
    e1.blog = 123
    print e1.blog # 123
    print e2.blog # 123
    print id(e1)
    print id(e2)

if __name__ == "__main__":
    test()
    task = []
    for one in range(30):
        t = threading.Thread(target=worker)
        task.append(t)

    for one in task:
        one.start()

    for one in task:
        one.join()


这样我们确实是解决了多线程数据安全的问题。但是这时候如其它线程要获得Singleton实例的线程还是必须等待,锁的存在降低了效率,有性能损耗。

总结, 我自己会有选择性的使用单例模式,把单例模式封装成一个装饰器使用起来很方便。另外对于数据库,尤其是mysql,建议不要使用单例模式。


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

1 Response

  1. 名字(必须) 2016年11月28日 / 下午4:11

    直接把类当模块导入是不是也是单例模式?

发表评论

邮箱地址不会被公开。 必填项已用*标注