为什么用Process调用multiprocessing模块可以创建相同的实例?
Why to call multiprocessing module with Process can create same instance?
我的平台信息:
uname -a
Linux debian 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux
python3 --version
Python 3.9.2
注意:加锁可以使Singletonclass生效,那不是我的问题,不用讲进程锁。
将在不同状态下执行的相同部分:
- 单例class
class Singleton(object):
def __init__(self):
pass
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
- 进程中的工作函数
import time,os
def task():
print("start the process %d" % os.getpid())
time.sleep(2)
obj = Singleton.instance()
print(hex(id(obj)))
print("end the process %d" % os.getpid())
创建多进程处理pool
方式:
from multiprocessing.pool import Pool
with Pool(processes = 4) as pool:
[pool.apply_async(func=task) for item in range(4)]
#same effcet with pool.apply ,pool.map,pool.map_async in this example,i have verified,you can try again
pool.close()
pool.join()
结果如下:
start the process 11986
start the process 11987
start the process 11988
start the process 11989
0x7fd8764e04c0
end the process 11986
0x7fd8764e05b0
end the process 11987
0x7fd8764e0790
end the process 11989
0x7fd8764e06a0
end the process 11988
所有子进程都有自己的内存,它们之间不共享space,它们不知道其他进程已经创建了一个实例,所以它输出不同的实例。
使用Process
方式创建多进程:
import multiprocessing
for i in range(4):
t = multiprocessing.Process(target=task)
t.start()
结果如下:
start the process 12012
start the process 12013
start the process 12014
start the process 12015
0x7fb288c21910
0x7fb288c21910
end the process 12014
end the process 12012
0x7fb288c21910
end the process 12013
0x7fb288c21910
end the process 12015
为什么要用这种方式创建同一个实例?multiprocessing模块的工作原理是什么?
@Reed Jones,你提供的相关post我看了很多遍了。
在 lmjohns3 的回答中:
So the net result is actually the same, but in the first case you're guaranteed to run foo and bar on different processes.
第一种情况是 Process 子模块,Process 将保证 运行 在不同的进程上,所以在我的例子中:
import multiprocessing
for i in range(4):
t = multiprocessing.Process(target=task)
t.start()
它应该导致多个(可能是 4 个或不是,至少大于 1 个)实例而不是同一个实例。
我确信 material 不能解释我的情况。
正如在 回答中所解释的那样,id
实现是特定于平台的,不是保证跨多个进程的唯一标识符的好方法。
具体来说,在 CPython 中,id
returns 对象在它自己的进程地址中的指针 space。大多数现代操作系统使用称为 Virtual Memory.
的方法抽象计算机内存
你观察到的是实际不同的物体。然而,它们似乎具有相同的标识符,因为每个进程在其自身内存地址的相同偏移量中分配该对象 space。
池中没有发生这种情况的原因很可能是由于池在 运行 [=] 之前在工作进程中分配了多个资源(管道、计数器等)。 12=] 函数。因此,它充分随机化了进程地址 space 利用率,使得对象 ID 在它们的同级进程中显得不同。
我的平台信息:
uname -a
Linux debian 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux
python3 --version
Python 3.9.2
注意:加锁可以使Singletonclass生效,那不是我的问题,不用讲进程锁。
将在不同状态下执行的相同部分:
- 单例class
class Singleton(object):
def __init__(self):
pass
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
- 进程中的工作函数
import time,os
def task():
print("start the process %d" % os.getpid())
time.sleep(2)
obj = Singleton.instance()
print(hex(id(obj)))
print("end the process %d" % os.getpid())
创建多进程处理pool
方式:
from multiprocessing.pool import Pool
with Pool(processes = 4) as pool:
[pool.apply_async(func=task) for item in range(4)]
#same effcet with pool.apply ,pool.map,pool.map_async in this example,i have verified,you can try again
pool.close()
pool.join()
结果如下:
start the process 11986
start the process 11987
start the process 11988
start the process 11989
0x7fd8764e04c0
end the process 11986
0x7fd8764e05b0
end the process 11987
0x7fd8764e0790
end the process 11989
0x7fd8764e06a0
end the process 11988
所有子进程都有自己的内存,它们之间不共享space,它们不知道其他进程已经创建了一个实例,所以它输出不同的实例。
使用Process
方式创建多进程:
import multiprocessing
for i in range(4):
t = multiprocessing.Process(target=task)
t.start()
结果如下:
start the process 12012
start the process 12013
start the process 12014
start the process 12015
0x7fb288c21910
0x7fb288c21910
end the process 12014
end the process 12012
0x7fb288c21910
end the process 12013
0x7fb288c21910
end the process 12015
为什么要用这种方式创建同一个实例?multiprocessing模块的工作原理是什么?
@Reed Jones,你提供的相关post我看了很多遍了。
在 lmjohns3 的回答中:
So the net result is actually the same, but in the first case you're guaranteed to run foo and bar on different processes.
第一种情况是 Process 子模块,Process 将保证 运行 在不同的进程上,所以在我的例子中:
import multiprocessing
for i in range(4):
t = multiprocessing.Process(target=task)
t.start()
它应该导致多个(可能是 4 个或不是,至少大于 1 个)实例而不是同一个实例。
我确信 material 不能解释我的情况。
正如在 id
实现是特定于平台的,不是保证跨多个进程的唯一标识符的好方法。
具体来说,在 CPython 中,id
returns 对象在它自己的进程地址中的指针 space。大多数现代操作系统使用称为 Virtual Memory.
你观察到的是实际不同的物体。然而,它们似乎具有相同的标识符,因为每个进程在其自身内存地址的相同偏移量中分配该对象 space。
池中没有发生这种情况的原因很可能是由于池在 运行 [=] 之前在工作进程中分配了多个资源(管道、计数器等)。 12=] 函数。因此,它充分随机化了进程地址 space 利用率,使得对象 ID 在它们的同级进程中显得不同。