Bootstrap

Python单例模式的代码实现和原理

Python单例设计模式的代码实现

import threading
import time


class Singleton(object):  
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance



class Bus(Singleton):
    lock = threading.RLock()

    def sendData(self, data):
        self.lock.acquire()
        time.sleep(3)
        print("Sending Signal Data...", data)
        self.lock.release()



class VisitEntity(threading.Thread):
    my_bus = ""
    name = ""

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def run(self):
        self.my_bus = Bus()
        self.my_bus.sendData(self.name)


if __name__ == "__main__":
    for i in range(3):
        print("Entity %d begin to run..." % i)
        my_entity = VisitEntity()
        my_entity.setName("Entity_"+str(i))
        my_entity.start()

这段代码实现并演示了Python中的单例模式,下面详细解释其代码实现和原理:

代码实现

单例类 Singleton 的定义:

class Singleton(object):  
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance
  • new 是Python类的一个特殊方法,用于创建并返回一个实例化对象。在单例模式里,它首先检查类属性 _instance 是否存在。如果不存在,就通过调用父类的 new 方法来创建一个新实例,并将其赋值给 _instance ;如果已经存在,直接返回这个已有的实例。
    Bus 类:
class Bus(Singleton):
    lock = threading.RLock()

    def sendData(self, data):
        self.lock.acquire()
        time.sleep(3)
        print("Sending Signal Data...", data)
        self.lock.release()
  • Bus 类继承自 Singleton 类,也就继承了单例的特性。它定义了一个线程锁 lock ,用于在多线程环境下同步访问资源, sendData 方法用于发送数据,通过获取锁、模拟耗时操作、释放锁来保证线程安全。
    VisitEntity 线程类:
class VisitEntity(threading.Thread):
    my_bus = ""
    name = ""

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def run(self):
        self.my_bus = Bus()
        self.my_bus.sendData(self.name)
  • VisitEntity 继承自 threading.Thread ,重写了 run 方法。在 run 方法中,它获取 Bus 类的单例实例,并调用其 sendData 方法发送数据,模拟多线程访问单例对象的场景。
    主程序部分:
if __name__ == "__main__":
    for i in range(3):
        print("Entity %d begin to run..." % i)
        my_entity = VisitEntity()
        my_entity.setName("Entity_"+str(i))
        my_entity.start()
  • 在主程序中,创建了3个 VisitEntity 线程,为每个线程设置名字后启动它们,观察多线程环境下单例对象的运行情况。

原理

  • 单例模式的核心目标:确保一个类只有一个实例,并提供一个全局访问点。在这段代码里,利用 new 方法的特性,类第一次实例化时创建对象,后续实例化请求都返回这个已创建好的对象,以此保证整个程序生命周期内特定类的实例唯一性。
  • 线程安全性:由于多线程环境下,多个线程可能同时尝试创建实例,代码引入了线程锁( RLock )。在 Bus 类的 sendData 方法中,当线程访问共享资源(这里模拟发送数据的操作)时,先获取锁,操作完成后释放锁,防止数据竞争和不一致问题,保证单例模式在并发场景下正常工作。运行这段代码,会发现虽然有多个线程尝试访问 Bus 实例,但它们操作的是同一个实例,并且按顺序依次执行 sendData 方法。
;