python Singleton 模式

筅森魡賤 提交于 2020-12-17 15:36:16

Singleton 模式,中文既为 单实例模式 。

一、代码示例

看一下普通的类:


class Normal(object):
    _instance = []

    config = ''

    def set(self,value):
        self.config = value

    def get(self):
        return self.confg

if __name__ == '__main__':
    s1 = Normal()
    s1.set('s1')

    s2 = Normal()
    s2.set('s2')

    print id(s1)
    print id(s2)
    print s1.get()
    print s2.get()
运行结果 :



ubuntu@yee:/tmp$ python t.py 
139782948272976
139782948273040
s1
s2

可以看到,代码中生成了两个实例,每个实例都拥有自己的内存空间。

接下来看单实例的代码示例:

class Singleton(object):
    _instance = []

    config = ''

    def __new__(cls,*args,**kwargs):
        if not cls._instance:
            cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
        return cls._instance

    def set(self,value):
        self.config = value

    def get(self):
        return self.config

if __name__ == '__main__':
    s1 = Singleton()
    s1.set('config:s1')
    
    s2 = Singleton()
    s2.set('config:s2')

    print id(s1)
    print id(s2)
    print s1.get()
    print s2.get()
ubuntu@yee:/tmp$ python t.py 
<__main__.Singleton object at 0x7f948b034c10>
<__main__.Singleton object at 0x7f948b034c10>
140275964136464
140275964136464
config:s2
config:s2
看到s2和s1 是同一个实例,所使用的都是同一个内存空间,所以 s1.set() 和s2.set()是设置了同一个变量 。


但是以上的代码也会有一个问题:线程安全

如果并发运行了两个线程,都检测到当前的  cls._instance = null ,那么都会创建新的线程,此时就全乱了。所以,我们需要加锁 

#!/usr/bin/python  
#-*- coding:utf8  -*-

import threading
import time
class Singleton(object):
    _instance = []
    config = ''

    def __new__(cls,*args,**kwargs):
        if not cls._instance:
            print  "I will lock thread"
            mlock = threading.Lock()
            mlock.acquire()
            cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
            mlock.release()

        return cls._instance

    def set(self,value):
        self.config = value

    def get(self):
        return self.config

def execute():
    s1 = Singleton()
    print str(id(s1)) + "\n"

if __name__ == '__main__':
    thread1  =  threading.Thread(target=execute)
    thread2  =  threading.Thread(target=execute)
    thread1.start()
    thread2.start()
只有第一次创建实例的时候才会加锁,所以不用担心会影响性能 。

搞清楚了上面的代码之后,就可以总结出单实例的优点了:

节省内存空间

二、单实例的使用场景 :

比方说,

OS在开机之后,会维护一份用户的配置文件,这份文件 从开机到关机期间只需要有一份,并且常驻内存之中。这个时间就需要使用单实例。

单实例可以使系统不必在用户去修改某一项配置的时候重新new一个实例,单实例对象是全局的,常驻内存的,所以只需要直接赋值就可以了。


三、为什么需要避免使用单实例

请自行google : why singleton  bad

(使用百度的程序猿不是好程序猿)

http://www.cnblogs.com/vwxyzh/archive/2010/07/17/1779620.html

http://www.btsmth.com/show_topic.php?en_name=SoftEng&gid=81604

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!