方法一:装饰器
利用装饰器只会执行一次的特性
import time import threading def singleton(cls): _instance_lock = threading.Lock() instances = []# 为什么这里不直接为None,因为内部函数没法访问外部函数的非容器变量 def getinstance(*args, **kwargs): if not instances: with _instance_lock: if not instances: instances.append(cls(*args, **kwargs)) return instances[0] return getinstance @singleton class Foo: pass f1 = Foo() f2 = Foo() print(id(f1), id(f2))
方法二:在做线程中的不使用锁
import time import threading class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): time.sleep(0.1) cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance class Foo(Singleton): def __init__(self): pass obj_list = [] def task(arg): obj_list.append(Foo()) for i in range(10): t = threading.Thread(target=task, args=(i,)) t.start() time.sleep(3) for obj in obj_list: print(id(obj), id(obj)) 42769992 42769992 42679096 42679096 42573776 42573776 35682288 35682288 42553072 42553072 42728136 42728136 42728248 42728248 42728080 42728080 42728528 42728528 42764552 42764552
方法二:在做线程中的使用锁
import time import threading class Singleton(object): _instance_lock = threading.Lock() def __new__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): time.sleep(0.1) with cls._instance_lock: if not hasattr(cls, "_instance"): cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance class Foo(Singleton): def __init__(self): pass obj_list = [] def task(arg): obj_list.append(Foo()) for i in range(10): t = threading.Thread(target=task, args=(i,)) t.start() time.sleep(3) for obj in obj_list: print(id(obj), id(obj)) 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384 42573384