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'}

posted @ 2020-10-28 20:25  maday  阅读(85)  评论(0)    收藏  举报