美文网首页
python 多进程基础

python 多进程基础

作者: rfkimi | 来源:发表于2018-07-01 01:01 被阅读0次

    进程与线程

    1、定义

    进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

    线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

    2、关系

    一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

    相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

    3、区别

    进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

    • 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

    • 线程的划分尺度小于进程,使得多线程程序的并发性高。

    • 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

    • 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

    • 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

    4.优缺点

    线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

    python多进程模块

    1. 多进程模块multiprocessing
    #!/usr/bin/env python
    # -*- coding: utf-8 -*- 
    import os
    from multiprocessing import Process
    def info(title):
        print(title)
        print('module name:', __name__)
        print('parent process name:', os.getppid())  # 打印父进程
        print('child process name:', os.getpid())  # 打印子进程
    def f(name):
        info('\033[31;1m called from child process function f \033[0m')  # 打印f函数的父子进程
        print'hello ' + name 
    def run(name):
        print name + ' ' + 'process create!'
    if __name__ == '__main__':
        info('\033[32;1m main process \033[0m')
        p = Process(target=f, args=('test1',))  # 创建进程实例
        p.start()
        p.join()
    

    输出结果

    main process 
    ('module name:', '__main__')
    ('parent process name:', 1981)
    ('child process name:', 2149)
     called from child process function f 
    ('module name:', '__main__')
    ('parent process name:', 2149)
    ('child process name:', 2150)
    hello test1
    

    2进程间通信queue、pipe
    queue

    #!/usr/bin/env python
    # -*- coding: utf-8 -*- 
    from multiprocessing import Queue,Process 
    def f(cq):
        cq.put(['my','name','is',['lilei','xixi']])  # 往队列中添加一个元素 
    if __name__ == '__main__':
        mq = Queue()            # 定义进程队列实例
        mq.put('fome main')     # 往队列中添加一个元素
        p = Process(target=f, args=(mq,))  # 创建一个子进程,并将mq传给子进程
        p.start()                       # 启动
        p.join()                        # 等待子进程执行完毕
        print('444',mq.get_nowait())  # 获取队列元素
        print('444', mq.get_nowait())
    

    输出结果

    ('444', 'fome main')
    ('444', ['my', 'name', 'is', ['lilei', 'xixi']])
    

    pipe

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from multiprocessing import  Process,Pipe
    
    
    def f(conn):
        conn.send("from child1")  # 发送数据
        conn.send("from child2")  # 发送数据
        print('client recv:',conn.recv())  # 接收数据
        conn.close()
    
    
    if __name__ == '__main__':
        a_conn, b_conn = Pipe()
        p = Process(target=f, args=(b_conn, ))
        p.start()
        print(a_conn.recv())
        print(a_conn.recv())
        a_conn.send('from parent')  # 父进程发送数据
        p.join()
    

    输出结果

    from child1
    from child2
    ('client recv:', 'from parent')
    

    3进程间数据共享manager

    from multiprocessing import Process,Manager
    import os
    def run(d,l):
        d[os.getpid()] = os.getpid()   #以当前子进程的pid为key,同时pid也作为value
        l.append(os.getpid())           
        print(d,l)
    
    if __name__ == '__main__':
            with Manager() as manager:
                d = manager.dict()  #manager 字典
                l = manager.list()  #manager 列表
                p_list = []         #空的列表,为之后的添加进程实例
                for i in range(10): #启动多个子进程
                    p = Process(target=run,args=(d,l))#起一子进程,执行run参数d,l
                    p.start()
                    p_list.append(p)  #添加进程实例至列表
                for r in p_list:    #循环子进程
                    r.join()          #等待子进程结束
                print(d)            #打印最终的字典
                print(l)            #打印最终的列表
    

    输出结果

    {3604: 3604} [3604]
    {6992: 6992, 3604: 3604} [3604, 6992]
    {6992: 6992, 3752: 3752, 3604: 3604} [3604, 6992, 3752]
    {6992: 6992, 3752: 3752, 3604: 3604, 3056: 3056} [3604, 6992, 3752, 3056]
    {6992: 6992, 3752: 3752, 3604: 3604, 3056: 3056, 796: 796} [3604, 6992, 3752, 3056, 796]
    {6992: 6992, 3056: 3056, 3604: 3604, 3752: 3752, 796: 796, 5856: 5856} [3604, 6992, 3752, 3056, 796, 5856]
    {6992: 6992, 3056: 3056, 3604: 3604, 3752: 3752, 4748: 4748, 796: 796, 5856: 5856} [3604, 6992, 3752, 3056, 796, 5856, 4748]
    {6992: 6992, 3056: 3056, 3604: 3604, 3752: 3752, 4748: 4748, 796: 796, 5856: 5856, 6684: 6684} [3604, 6992, 3752, 3056, 796, 5856, 4748, 6684]
    {6992: 6992, 3056: 3056, 3604: 3604, 3752: 3752, 4748: 4748, 796: 796, 5856: 5856, 6684: 6684, 6432: 6432} [3604, 6992, 3752, 3056, 796, 5856, 4748, 6684, 6432]
    {6992: 6992, 3056: 3056, 3604: 3604, 5356: 5356, 3752: 3752, 4748: 4748, 796: 796, 5856: 5856, 6684: 6684, 6432: 6432} [3604, 6992, 3752, 3056, 796, 5856, 4748, 6684, 6432, 5356]
    {6992: 6992, 3056: 3056, 3604: 3604, 5356: 5356, 3752: 3752, 4748: 4748, 796: 796, 5856: 5856, 6684: 6684, 6432: 6432}
    [3604, 6992, 3752, 3056, 796, 5856, 4748, 6684, 6432, 5356]
    

    相关文章

      网友评论

          本文标题:python 多进程基础

          本文链接:https://www.haomeiwen.com/subject/aroxuftx.html