方法一:装饰器
利用装饰器只会执行一次的特性
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