全局变量在多个进程中不共享:
进程之间的数据是独立的,默认情况下互不影响
原理是创建子进程是会将主进程的资源copy一份给子进程,子进程拥有一份与主进程一样的代码,子进程会将这代码在执行一遍。但是if__name__=='__main__':
内部的代码就不会执行了。
由于进程之间的数据是独立的。主进程中的全局变量,在进程中也复制了一份,他们名字一样,其实并不是同一个。
import multiprocessing
import os
#主进程中定义全局变量
print('------------------' + '进程%s' % multiprocessing.current_process().name)
num = [99,100]
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
def work1():
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print("work1正在运行......")
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print('\n')
def work2():
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print("work2正在运行......")
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print('\n')
if __name__ == '__main__':
print('主进程.......................')
print("主进程中的num的id %s"%id(num))
print('\n')
p1 = multiprocessing.Process(target=work1)
p1.start()
p1.join()
p2 = multiprocessing.Process(target=work2)
p2.start()
p2.join()
print('主进程结束了....................')
最上面的代码,写在main之外的:
这部分语句,子进程也会执行,因为子进程创建时,会copy一份主进程的代码,包括后面的函数定义都会执行一遍,main内部的自然不会了
print('------------------' + '进程%s' % multiprocessing.current_process().name)
num = [99,100]
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
所以这部分代码会被主进程,子进程1,子进程2分别执行一次,根据每次输出的id(num),我们就可以发现,两个子进程内部也会再次创建一次叫做num的变量,同时num指向的是一个可变类型,再次创建的时候就会重新申请内存,所以id(num)是不一样的。
上面每部分结果对应着的代码,可以看到的是主进程,子进程1,子进程2中输出的id(num)是分别不同的,而且每个进程也确实的执行了这部分代码
#主进程中定义全局变量
print('------------------' + '进程%s' % multiprocessing.current_process().name)
num = [99,100]
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
同时每个进程的内部,输出的id(num)是一样的,如下图:
就是说,每个子进程内部都有一个叫num的变量,不同进程的num指向的地址是不一样的。所以子进程内部使用的这个num,其实就是子进程自己的,主进程的num你是拿不到的,因为进程之间是独立的。
代码修改一下:
#主进程中定义全局变量
print('------------------' + '进程%s' % multiprocessing.current_process().name)
num = [99,100]
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
def work1():
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print("work1正在运行......")
print(id(num))
num.append(101)
print(num)
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print('\n')
def work2():
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print("work2正在运行......")
print(id(num))
num.append(102)
print(num)
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print('\n')
if __name__ == '__main__':
print('主进程.......................')
print("主进程中的num的id %s"%id(num))
print('\n')
p1 = multiprocessing.Process(target=work1)
p1.start()
p1.join()
p2 = multiprocessing.Process(target=work2)
p2.start()
p2.join()
print('进程结束了')
print("主进程中的num是%s"%num)
print('主进程结束了....................')
可以看出子进程是修改不了主进程中的全局变量的。
如果num是不可变类型
代码为:
# 主进程中定义全局变量
print('------------------' + '进程%s' % multiprocessing.current_process().name)
num = 99
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
def work1():
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print("work1正在运行......")
global num #声明使用外面的num
print(id(num))
num = 100
print(id(num)) #修改后在输出一下id
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print('\n')
def work2():
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print("work2正在运行......")
print(id(num))
print('------------------' + '进程%s' % multiprocessing.current_process().name)
print('\n')
if __name__ == '__main__':
print('主进程.......................')
print("主进程中的num的id %s"%id(num))
print('\n')
p1 = multiprocessing.Process(target=work1)
p1.start()
p1.join()
p2 = multiprocessing.Process(target=work2)
p2.start()
p2.join()
print("主进程中的num的id %s" % id(num))
print('主进程结束了....................')
由于num现在指向的是不可变对象,同时是python中的小整数对象,拥有固定的内存,所以不论是主进程还是子进程,id(num)的结果是一样的。
在子进程1中声明使用的外部num,并不是主进程中的num ,而是子进程1中的num,因为子进程1会copy主进程的代码,上面那部分一执行,子进程1就有了自己的num,使用的时候就使用了自己的num,而且进程是独立的,你也访问不到主进程中的num。
所以总体来说,主进程中的全局变量,子进程中会有一份一模一样的,子进程中访问和修改的其实都是自己的变量,只是和主进程中的那个变量名字一样。子进程不能修改到主进程中的全局变量,因为进程之间是独立的。
这是我目前的理解,不能保证准确。