• 进程的开启方式 进程的join方法 进程间的内存隔离 其他相关方法 守护进程 互斥锁


    #创建进程的方式一
    from multiprocessing import Process
    import time
    
    def task(name):
        print('%s is running'%name)
        time.sleep(2)
        print('%s is over'%name)
    
    '''
    # 注意:在window系统里,创建进程会将代码以模块的方式从头到尾加载一遍
    # 创建进程的代码块要写在 if __name__ == '__main__': 里面,避免出错
    # 强调:函数名一旦加括号,执行优先级最高,会马上执行。
    '''
    
    if __name__ == '__main__':
        p = Process(target=task,args=('michael',)) #这句话实例了一个Process对象
        p.start()   #告诉操作系统创建一个进程
        print('我是主进程!')
        
    #实际输出的结果:我是主进程!
                     #michael is running
                     #michael is over
    #解释:操作系统创建进程的时间比代码运行的速度要慢,所以先将主进程的输出结果打印出来
    
    
    
    #创建进程的方式二
    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
    
        def __init__(self,name):
            super().__init__()
            self.name = name
        #必须写run方法
        def run(self):
            print('%s is running'%self.name)
            time.sleep(2)
            print('%s is over'%self.name)
    
    if __name__ == '__main__':
        obj = MyProcess('michael')
        obj.start()
        print('我是主进程!')
    

     

    join方法
    
    from multiprocessing import Process
    import time
    
    def task(name,n):
        print('%s is running'%name)
        time.sleep(n)
        print('%s is over'%name)
    
    # if __name__ == '__main__':
    #     p1 = Process(target=task,args=('egon1',1))
    #     p2 = Process(target=task,args=('egon2',2))
    #     p3 = Process(target=task,args=('egon3',3))
    #     start_time = time.time()  #系统创建进程的时间
    #     p1.start()  #这行代码只是告诉操作系统需要创建进程
    #     p2.start()
    #     p3.start()
    #     p1.join()    #join的作用: 让主进程等待子进程结束,然后再运行主进程,并不会影响子进程的运行
    #     p2.join()
    #     p3.join()
    #     print('我是主进程',time.time()-start_time)  #记录主进程等待的时间
    
    # 上面冗余的代码可以简化
    if __name__ == '__main__':
        start_time = time.time()
        p_list = []
        for i in range(3):
            p = Process(target=task,args=('子进程%s'%i,i))
            p.start()
            p_list.append(p)
        for p in p_list:
            p.join()
        print('主进程',time.time()-start_time)
    

      

    #进程间数据隔离
    from multiprocessing import Process
    x = 100
    def task():
        global x
        x = 0
    
    if __name__ == '__main__':
        p = Process(target=task)
        p.start()
        p.join()  #加上join 为了确保先运行子进程
        print('主进程',x)   #主进程 100
    #结果说明:每个进程之间的数据是彼此隔离的!
    

      

    #进程对象其他相关方法
    from multiprocessing import Process
    import time
    import os
    
    def task():
        print('子进程自己的pid',os.getpid())
        time.sleep(3)
        print('子进程父级的pid',os.getppid())
    
    #is_alive的使用   判断子进程是否存活
    if __name__ == '__main__':
        p = Process(target=task)
        p.start()
        print(p.is_alive())  #True  此时的子进程是存在的
        p.join(4)   #join()里的参数需要大于sleep的参数,不然还是会自动运行,当没有参数时,默认等子进程执行完
        print(p.is_alive())  #False   is_alive() 放在join后会自动将子进程销毁,因此不存在
        print('我是主进程')
        print(p.pid)   #查看子进程自己的pid
    
    # termininate的使用  杀死子进程
    if __name__ == '__main__':
        p = Process(target=task)
        p.start()
        p.terminate() #关闭进程,不会立即关闭,所以is_alive立刻查看的结果可能还是存活
        print(p.is_alive())  #True
        p.join()
        print('我是主进程!')
        print(p.is_alive())  #False
    

      

    #守护进程
    主进程创建守护进程:
        特点1:守护进程会在主进程代码执行结束后就终止
        特点2:守护进程内无法再开启子进程,否则会抛出异常
    
    例子1:
    from multiprocessing import Process
    import time
    def task(name):
        print('%s正活着'%name)
        time.sleep(2)
        print('%s正在死亡'%name)
    
    if __name__ == '__main__':
        p = Process(target=task,args=('子进程',))
        p.daemon = True #一定要在p.start前设置,设置子线程p为主线程的守护进程,禁止p创建子线程
        #并且父进程代码执行结束,p也将终止运行,由于操作系统的处理时间较慢,正常情况下都是直接执行完父进程就结束了
        p.start()
        # p.daemon = True 将daemon放在 start 后面会报错!
        print('主进程正在死亡')
    
    
    
    例子2:
    from multiprocessing import Process
    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(1)
        print("end456")
    
    if __name__ == '__main__':
    
        p1=Process(target=foo)
        p2=Process(target=bar)
        p1.daemon=True
        p1.start()
        p2.start()
        # p1.join()   #当加上了join后,子进程会正常执行,此时的daemon好像不起作用了!下面有详解!
        print("main-------")
    

      

    #join 与daemon之间的关系
    
    1 Python 默认参数创建线程后,不管主线程是否执行完毕,都会等待子线程执行完毕才一起退出,有无join结果一样 
    2 如果创建线程,并且设置了daemon为true,即thread.setDaemon(True), 则主线程执行完毕后自动退出,
            不会等待子线程的执行结果。而且随着主线程退出,子线程也消亡。
    3 join方法的作用是阻塞,等待子线程结束,join方法有一个参数是timeout,即如果主线程等待timeout,
            子线程还没有结束,则主线程强制结束子线程。 
    4 如果线程daemon属性为False, 则join里的timeout参数无效。主线程会一直等待子线程结束。 
    5 如果线程daemon属性为True, 则join里的timeout参数是有效的, 主线程会等待timeout时间后,结束子线程。
        此处有一个坑,即如果同时有N个子线程join(timeout),那么实际上主线程会等待的超时时间最长为 N timeout, 
        因为每个子线程的超时开始时刻是上一个子线程超时结束的时刻。
    

      

    #僵尸进程与孤儿进程
    '''回收子进程的pid等信息的两种方式:
        1、父进程正常结束
        2、join方法
    '''
    

      

    互斥锁
    #模拟抢票
    from multiprocessing import Process,Lock
    import json
    import time
    import random
    
    def search(i):
        with open('info','r',encoding='utf-8') as f:
            data = json.load(f)
        print('剩余票数为%s'%data.get('ticket'))
    
    def buy(i):
        #买票前还需要查看是否还有票!
        with open('info','r',encoding='utf-8')as f:
            data = json.load(f)
        #模拟网络延迟
        time.sleep(random.randint(1,3))
        if data.get('ticket') > 0:
            data['ticket'] -= 1 #买票,库存减一
            #将更新的信息重新写入文件
            with open('info','w',encoding='utf-8')as f:
                json.dump(data,f)
            print('用户%s抢票成功'%i)
        else:
            print('没有余票,用户%s抢票失败!'%i)
    
    def run(i,mutex):
        search(i)    #所有的进程查询的余票数为一致的,大家的起点一致     这一步应该放入到mutex.acquire下
        mutex.acquire()  #抢锁 一把锁只能被一个人抢到,其他人等待锁被释放
        buy(i)
        mutex.release()  #释放锁,其他人又处于同一地步了
    
    if __name__ == '__main__':
        mutex = Lock()
        for i in range(10):
            p = Process(target=run,args=(i,mutex))
            p.start() #产生10个子进程
    

     

    互斥锁补充:不要随便使用
        特点:牺牲了效率但是保证了数据的安全,解决了多个进程操作同一分数据,造成数据不安全的情况。
    
        锁一定要在主进程中创建,给子进程使用:
        加锁会将并发变成串行
        锁通常用在对数据操作的部分,并不是对进程全程加锁        
    

      

     

    #小点:
    from multiprocessing import Process
    import time, os
    def task():
        print('%s is running' % os.getpid())
        # time.sleep(3)
    if __name__ == '__main__':
        p = Process(target=task)
        p.start()
        print(p.is_alive())  #True
        p.join()  # 等待进程p结束后,join函数内部会发送系统调用wait,去告诉操作系统回收掉进程p的id号
        print(p.pid)  # ???此时能否看到子进程p的id号    可以看到
        print(p.is_alive())  #False
        print('主')
        print(p.pid)   #依然存在
    '''
    上述问题的解释:
    p.join()是向操作系统发送请求,告知操作系统 子进程p的id号不需要再占用了,回收就可以,
    此时在父进程内还可以看到p.pid,但此时的p.pid是一个无意义的id号,因为操作系统已经将该编号回收
    '''
    

      

     

  • 相关阅读:
    JS倒计时执行操作
    美化radio和checkbox样式
    ajax 多个表单值问题,表单序列化加其它表单值
    .net中的路径问题
    Response.Redirect 打开新窗口的两种方法
    GRIDVIEW FINDCONTROL的使用
    如何验证gridview控件的编辑行?如何获得gridview模板列<ItemTemplate/>中Label值?
    在Repeater的HeaderTemplate和FooterTemplate模板中寻找控件FindControl
    在GridView中使用FindControl(2)
    构造函数(C# 编程指南)
  • 原文地址:https://www.cnblogs.com/changwenjun-666/p/10821023.html
Copyright © 2020-2023  润新知