在Python中,如果要创建一个单例,通常有两种方式。
第一种,利用python的模块的特性,先创建一个对象,其他的模块通过导入此模块,来实现单例。
1
2
3
4
5
6
7
8
9
10
11
12
| class SingleCls:
def __init__(self):
self.__info_list = list()
# self.__info_list = multiprocessing.Manager().list()
def AddMessage(self, message):
self.__info_list.append("Hello %s" % message)
def __repr__(self):
return str(self.__info_list)
single_obj = SingleCls()
|
另一种,使用python一切皆对象的属性,类也属于对象,使用类中的类属性来保存创建好的单例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| class SingleCls:
_instance = None
def __new__(cls, *args, **kw):
if not cls._instance:
cls._instance = super(SingleCls, cls).__new__(cls, *args, **kw)
return cls._instance
def __init__(self):
self.__info_list = list()
def AddMessage(self, message):
self.__info_list.append("Hello %s" % message)
def __repr__(self):
return str(self.__info_list)
single_obj = SingleCls()
|
单例的本质是,不同模块使用的是同一个对象,这需要在 ‘第三方’ 的领土上创建。
可是在多进程的环境中,结果却不一定了。
- 多进程的环境中,子进程通过fork产生,会拷贝父进程中的变量,单例也不例外。
- 所以,子进程中的单例对象,已经各不相同了!
- 导致的结果就是,虽然子进程中对单例对象进行了很多操作,但是父进程中的单例对象却未发生改变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| def func(m):
single_obj.AddMessage(m)
print("single_obj {m} -> ".format(m=m), single_obj)
func("1")
func("2")
func("3")
pool = multiprocessing.Pool(4)
pool.apply(func, args=("First",))
pool.apply(func, args=("Second",))
pool.apply(func, args=("Third",))
# pool.apply(single_obj.AddMessage, args=("First",))
# pool.apply(single_obj.AddMessage, args=("Second",))
# pool.apply(single_obj.AddMessage, args=("Third",))
pool.close()
pool.join()
print(single_obj)
|
输出如下所示:
1
2
3
4
5
6
7
| single_obj 1 -> ['Hello 1']
single_obj 2 -> ['Hello 1', 'Hello 2']
single_obj 3 -> ['Hello 1', 'Hello 2', 'Hello 3']
single_obj First -> ['Hello 1', 'Hello 2', 'Hello 3', 'Hello First']
single_obj Second -> ['Hello 1', 'Hello 2', 'Hello 3', 'Hello Second']
single_obj Third -> ['Hello 1', 'Hello 2', 'Hello 3', 'Hello Third']
['Hello 1', 'Hello 2', 'Hello 3']
|
Author
Alfons
LastMod
2019-06-26
License
Creative Commons BY-NC-ND 3.0