7.进程
进程和线程之间的区别:
1.线程们可以共享一块地址空间,进程独立享有一个地址空间
2.线程可以进入进程修改他的数据片,即共享一个数据
3.线程之间可以通信,进程之间不能通信
4.很容易就能创建一个新的线程,创建新进程需要拷贝父进程,开销很大
5.线程之间可以互相操作,进程不可以
6.主线程可以影响子线程,主进程无法影响子进程
进程的概念:
进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
进程一推资源联系整合在一起,一个进程可以有多个线程
线程之间可以进行资源共享,但是进程不行。
线程和进程的执行速度一样快。
多线程中,进程会优先调度当前电脑的cpu,一个进程调用一个cpu,如果cpu数目不够,就只能靠cpu切换来完成多进程
注意事项:
1,在unix平台上,当某个程序终结后,该进程需被其父进程调用wait,否则称为僵尸进程,
有必要对每个process对象调用join方法
2,对进程优先考虑pipe和queue,避免使用lock/event/等同步方式
3,多进程程序中,每个进程有自己独立的内存空间,应该避免多线程共享资源
在windows系统下,想启动一个子进程,必须加上__name__=='__main__'
创建多进程步骤和方法
引入模块
from multiprocessing import Process
创建子进程对象 p=Process(target=函数名,arges=参数)
启动子进程 p.start()
添加join方法 p.join()
获取当前进程的进程号 os.getpid()
获取当前进程的父进程号 os.getppid()
举例:
函数型创建多进程
from multiprocessing import Process import time def f(name): time.sleep(2) print('hello',name,time.ctime()) if __name__=='__main__': p_list=[] for i in range(4): #创建4个子进程 p=Process(target=f,args=('tom',)) p_list.append(p) for p in p_list: p.start() for i in p_list: i.join()
类型创建多进程(一定要继承父类的__init__,在类中,实现run方法,在方法里写入进程的功能)
class MyProcess(Process): def __init__(self,name): super(MyProcess,self).__init__() #继承父类的__init__ self.name=name def run(self): time.sleep(2) print('hello',self.name,time.ctime()) if __name__=='__main__': p_list=[] for i in range(3): p=MyProcess('tom') #实例化一个进程对象 p.start() #启动进程 p_list.append(p) for p in p_list: p.join()
进程之间的关系:
每个进程都有一个父进程,最终可以追溯到一个根进程
多线程程序中,子进程的父进程是当前的主进程,即main ,主进程的父进程是当前的程序,即pycharm
实现进程之间的通信
queuq
线程中的队列是线程队列,进程中的队列是进程队列,两者有很大差别,不能混淆使用
from multiprocessing import Process,Queue def f(q,n): q.put([42,n,'hello']) if __name__=='__main__': q=Queue() p_list=[] for i in range(3): p=Process(target=f,args=(q,1)) #参数中有q,是为了将主进程中的队列传递给子进程,否则子进程无法识别队列 p_list.append(p) p.start() print(q.get()) print(q.get()) print(q.get()) for i in p_list: i.join()
参数中有q,是为了将主进程中的队列传递给子进程,否则子进程无法识别队列,
队列必须作为一个参数传递给子进程,否则无法使用
pipe
过pipe()可以得到主进程通道和子进程通道
将子进程通道作为参数传递给子进程函数,就可以用recv和send方法实现与主进程自建的通信,通信的方式与socket差不多
使用recv时,如果接收不到数据,程序也会进入阻塞状态
from multiprocessing import Process,Pipe def f(conn): conn.send([42,None,'hello']) # 使用子进程通道向主进程通道发送信息 conn.close() if __name__=='__main__': parent_con,child_con=Pipe() # 得到主进程通道和子进程通道 p=Process(target=f,args=(child_con,)) # 将子进程通道作为参数传递给子进程函数,创建新进程 p.start() print(parent_con.recv()) 使用主进程通道结束子进程的信息 p.join()
主进程发送一条数据时,只能有一个子进程会接收得到数据;每个子进程发送一条数据,有几个子进程,主进程就要接收几次
manage
使用manage实现进程之间共享数据:可以实现多进程之间对一个数据进行修改,如字典,列表
from multiprocessing import Process,Manager def f(d,l,n): #共有10个进程,每个进程都会执行该函数, d[n]='1' #根据n值不同,对字典添加的值也不同 d['2']=2 d[0.25]=None l.append(n) #根据n的不同,对列表添加的值不同 print(l) print(d) if __name__=='__main__': with Manager() as manage: d=manage.dict() #创建一个字典,内容为空 l=manage.list(range(5)) #创建一个列表,内容为[0,1,2,3,4] p_list=[] for i in range(10): p=Process(target=f,args=(d,l,i)) p.start() p_list.append(p) for i in p_list: i.join()
执行结果:
[0, 1, 2, 3, 4, 0]
{0: '1', '2': 2, 0.25: None}
[0, 1, 2, 3, 4, 0, 7]
{0: '1', '2': 2, 0.25: None, 7: '1'}
[0, 1, 2, 3, 4, 0, 7, 6]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1'}
[0, 1, 2, 3, 4, 0, 7, 6, 5]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1', 5: '1'}
[0, 1, 2, 3, 4, 0, 7, 6, 5, 9]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1', 5: '1', 9: '1'}
[0, 1, 2, 3, 4, 0, 7, 6, 5, 9, 4]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1', 5: '1', 9: '1', 4: '1'}
[0, 1, 2, 3, 4, 0, 7, 6, 5, 9, 4, 3]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1', 5: '1', 9: '1', 4: '1', 3: '1'}
[0, 1, 2, 3, 4, 0, 7, 6, 5, 9, 4, 3, 8]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1', 5: '1', 9: '1', 4: '1', 3: '1', 8: '1'}
[0, 1, 2, 3, 4, 0, 7, 6, 5, 9, 4, 3, 8, 2]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1', 5: '1', 9: '1', 4: '1', 3: '1', 8: '1', 2: '1'}
[0, 1, 2, 3, 4, 0, 7, 6, 5, 9, 4, 3, 8, 2, 1]
{0: '1', '2': 2, 0.25: None, 7: '1', 6: '1', 5: '1', 9: '1', 4: '1', 3: '1', 8: '1', 2: '1', 1: '1'}

浙公网安备 33010602011771号