一、使用__new__方法:
import threading
import time
class SingleClass:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
pass
二、并发单例:
存在线程安全问题,可能多个线程同时执行到创建_instance语句。
import threading
import time
class SingleClass:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
time.sleep(1)
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
pass
def get_single():
print(SingleClass())
threading.Thread(target=get_single).start()
threading.Thread(target=get_single).start()
运行结果:
<__main__.SingleClass object at 0x000001FA63C71DF0><__main__.SingleClass object at 0x000001FA62D49C40>
可以看到产生了两个不同的对象。
在__new__中使用线程锁保证线程安全。
import threading
import time
class SingleClass:
_instance_lock = threading.Lock()
_instance = None
def __new__(cls, *args, **kwargs):
with cls._instance_lock:
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
pass
def get_single():
print(SingleClass())
threading.Thread(target=get_single).start()
threading.Thread(target=get_single).start()
若要在多进程中实现单例,则必须使用多进程模块中的共享资源实现。
个人猜测是因为多进程全局变量不共享导致单例失效,欢迎明白的大佬指点。
import multiprocessing
from multiprocessing import Process, Queue
class SingleClass:
def __init__(self, a):
self.a = a
def get_single(d, lock, a):
lock.acquire()
if d.get('single', None) is None:
d['single'] = SingleClass(a)
lock.release()
print(d['single'].a)
if __name__ == '__main__':
m = multiprocessing.Manager()
d = m.dict()
lock = multiprocessing.Lock()
t = Process(target=get_single, args=(d, lock, 1))
t1 = Process(target=get_single, args=(d, lock, 2))
t.start()
t1.start()
t.join()
t1.join()
三、使用metaclass
class SingleClass(type):
_instance_lock = threading.Lock()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._instance = None
def __call__(self, *args, **kwargs):
with self._instance_lock:
if self._instance is None:
self._instance = super().__call__(*args, **kwargs)
return self._instance
class SubClass1(metaclass=SingleClass):
pass
四、使用装饰器
import threading
import time
def single(cls):
instance = None
instance_lock = threading.Lock()
def inner(*args, **kwargs):
nonlocal instance
with instance_lock:
if instance is None:
instance = cls(*args, **kwargs)
return instance
return inner
@single
class SingleClass():
pass
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)