Python 实现单例模式

程序员历来不缺对象,想 new 几个就 new 几个。程序员

对象.png

可是对象多了不免会出点问题,指不定哪天哪一个对象就爆炸了。单例模式就是为了解决这个问题,不管 new 了几回,都只能存在一个对象,相似一些网站的登陆,就是经过这种方式,实现只能有一个帐号登陆之类的功能。安全

首先能够简单地实现一下:网站

class Singleton(object):
    __instance = None

    def __init__(self, *args, **kwargs):
        pass

    @classmethod
    def get_instance(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = Singleton(*args, **kwargs)
        return cls.__instance


obj1 = Singleton.get_instance()
obj2 = Singleton.get_instance()

print(obj1)
print(obj2)

输出以下,能够看出两个对象 obj1obj2 是同一个地址,即这个时候只有一个对象。spa

<__main__.Singleton object at 0x0000015F47A2CC88>
<__main__.Singleton object at 0x0000015F47A2CC88>

但这种方法不是线程安全的线程

import threading
import time


class Singleton(object):
    __instance = None

    def __init__(self, *args, **kwargs):
        time.sleep(1)

    @classmethod
    def get_instance(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = Singleton(*args, **kwargs)
        return cls.__instance


def task():
    obj = Singleton.get_instance()
    print(obj)


for i in range(6):
    threading.Thread(target=task).start()

输出结果,出现了多个对象:code

<__main__.Singleton object at 0x0000028A133F1F48>
<__main__.Singleton object at 0x0000028A134C93C8>
<__main__.Singleton object at 0x0000028A134C9288>
<__main__.Singleton object at 0x0000028A134C9148>
<__main__.Singleton object at 0x0000028A134BEFC8>
<__main__.Singleton object at 0x0000028A134C9508>

并且上面这种方法只有第一次 get_instance() 的时候能给对象传递参数,总之有许多弊端。Python 提供了 __new__ 方法正好完美解决了这个问题,再加上锁,就能实现一个线程安全的单例模式对象

import threading
import time


class Singleton(object):
    __lock = threading.Lock()
    __instance = None

    def __new__(cls, *args, **kwargs):
        with cls.__lock:
            if not cls.__instance:
                cls.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self, *args, **kwargs):
        time.sleep(1)


def task():
    obj = Singleton()
    print(obj)


if __name__ == '__main__':
    for i in range(6):
        threading.Thread(target=task).start()

输出结果:blog

<__main__.Singleton object at 0x000001DA4A1C0F88>
<__main__.Singleton object at 0x000001DA4A1C0F88>
<__main__.Singleton object at 0x000001DA4A1C0F88>
<__main__.Singleton object at 0x000001DA4A1C0F88>
<__main__.Singleton object at 0x000001DA4A1C0F88>
<__main__.Singleton object at 0x000001DA4A1C0F88>
相关文章
相关标签/搜索