开启子进程的两种方式,孤儿进程与僵尸进程,守护进程,互斥锁,IPC机制,生产者与消费者模型

Posted xiejintao0914

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开启子进程的两种方式,孤儿进程与僵尸进程,守护进程,互斥锁,IPC机制,生产者与消费者模型相关的知识,希望对你有一定的参考价值。

开启子进程的两种方式

技术分享图片
# # # 方式一:
# from multiprocessing import Process
# import time
#
# def task(x):
#     print(‘%s is running‘ %x)
#     time.sleep(3)
#     print(‘%s is done‘ %x)
#
# if __name__ == ‘__main__‘:
#     # Process(target=task,kwargs={‘x‘:‘子进程‘})
#     p=Process(target=task,args=(‘子进程‘,)) # 如果args=(),括号内只有一个参数,一定记住加逗号
#     p.start() # 只是在操作系统发送一个开启子进程的信号
#
#     print(‘主‘)

# 导入from multiprocessing import Process
# 相当于在windows系统中调用了CreateProcess接口
# CreateProcess既处理进程的创建,也负责把正确的程序装入新进程。
# p.start() # 只是在操作系统发送一个开启子进程的信号

# 方式二:
# from multiprocessing import Process
# import time
#
# class Myprocess(Process):
#     def __init__(self,x):
#         super().__init__()
#         self.name=x
#
#     def run(self):
#         print(‘%s is running‘ %self.name)
#         time.sleep(3)
#         print(‘%s is done‘ %self.name)
#
# if __name__ == ‘__main__‘:
#     p=Myprocess(‘子进程1‘)
#     p.start()  #p.run()
#     print(‘主‘)



from multiprocessing import Process
import time


def task(x,n):
    print(%s is running % x)
    time.sleep(n)
    print(%s is done % x)


if __name__ == __main__:
    # Process(target=task,kwargs={‘x‘:‘子进程‘})
    p1 = Process(target=task, args=(子进程1,3))  # 如果args=(),括号内只有一个参数,一定记住加逗号
    p2 = Process(target=task, args=(子进程2,5))  # 如果args=(),括号内只有一个参数,一定记住加逗号
    p1.start()  # 只是在操作系统发送一个开启子进程的信号
    p2.start()  # 只是在操作系统发送一个开启子进程的信号

    print()
View Code
技术分享图片
#1、join(让父进程在原地等待,等到子进程运行完毕后(会触发wait功能,将子进程回收掉),才执行下一行代码)
# from multiprocessing import Process
# import time
#
# def task(name):
#     print(‘%s is running ‘ %name)
#     time.sleep(3)
#     print(‘%s is done ‘ % name)
#
#
# if __name__ == ‘__main__‘:
#     p=Process(target=task,args=(‘子进程1‘,))
#     p.start()  # 只是在操作系统发送一个开启子进程的信号,至于操作系统多久执行这个指令我们控制不了
#     p.join() # 让父进程在原地等待,等到子进程运行完毕后(会触发wait功能,将子进程回收掉),才执行下一行代码
#               #  将p占用的操作系统的pid回收
#     print(‘主‘)



# from multiprocessing import Process
# import time
#
# def task(name,n):
#     print(‘%s is running ‘ %name)
#     time.sleep(n)
#     print(‘%s is done ‘ % name)
#
#
# if __name__ == ‘__main__‘:
#     p1=Process(target=task,args=(‘子进程1‘,1))
#     p2=Process(target=task,args=(‘子进程2‘,2))
#     p3=Process(target=task,args=(‘子进程3‘,3))
#
#     start_time=time.time()
#     p1.start() # 只是在操作系统发送一个开启子进程的信号
#     p2.start() # 只是在操作系统发送一个开启子进程的信号
#     p3.start() # 只是在操作系统发送一个开启子进程的信号
#
#     p3.join()
#     p1.join()
#     p2.join()
#
#     stop_time=time.time()
#     print(‘主‘,(stop_time-start_time))


# from multiprocessing import Process
# import time
#
# def task(name,n):
#     print(‘%s is running ‘ %name)
#     time.sleep(n)
#     print(‘%s is done ‘ % name)
#
#
# if __name__ == ‘__main__‘:
#     p1=Process(target=task,args=(‘子进程1‘,1))
#     p2=Process(target=task,args=(‘子进程2‘,2))
#     p3=Process(target=task,args=(‘子进程3‘,3))
#
#     start=time.time()
#     p1.start()
#     p1.join()
#     p2.start()
#     p2.join()
#     p3.start()
#     p3.join()
#                 #  这叫串行
#     stop=time.time()
#     print(‘主‘,(stop-start))


# from multiprocessing import Process
# import time
#
# def task(name,n):
#     print(‘%s is running ‘ %name)
#     time.sleep(n)
#     print(‘%s is done ‘ % name)
#
#
# if __name__ == ‘__main__‘:
#     # p1=Process(target=task,args=(‘子进程1‘,1))
#     # p1.start()
#     # p2=Process(target=task,args=(‘子进程2‘,2))
#     # p2.start()
#     # p3=Process(target=task,args=(‘子进程3‘,3))
#     # p3.start()
#
#     p_l=[]
#     start=time.time()
#     for i in range(1,4):
#         p=Process(target=task,args=(‘子进程%s‘ %i,i))
#         p_l.append(p)
#         p.start()
#
#     # print(p_l)
#     for p in p_l:
#         p.join()
#
#     stop=time.time()
#
#     print(‘主‘,(stop-start))



# pid
# from multiprocessing import Process
# import time
# import os
#
# def task(n):
#     print(‘%s is running ‘ %os.getpid())
#     time.sleep(n)
#     print(‘%s is done ‘ % os.getpid())
#
#
# if __name__ == ‘__main__‘:
#     p1=Process(target=task,args=(10,))
#     # print(p1.pid)
#     p1.start()
#     print(p1.pid) # 父进程内查看子pid的方式
#     print(‘主‘)


from multiprocessing import Process
import time
import os

def task():
    print(自己的id:%s 父进程的id:%s  %(os.getpid(),os.getppid()))
    time.sleep(200)

if __name__ == __main__:
    p1=Process(target=task)
    p1.start()
    print(,os.getpid(),os.getppid())
    # 爹=》主--》儿子





# 了解
# from multiprocessing import Process,current_process # 子进程的名字(current_process)
# import time
#
# def task():
#     print(‘子进程[%s]运行。。。。‘ %current_process().name)
#     time.sleep(200)
#
# if __name__ == ‘__main__‘:
#     p1=Process(target=task,name=‘子进程1‘)
#     p1.start()
#     # print(p1.name)
#     print(‘主‘)




# from multiprocessing import Process,current_process
# import time
#
# def task():
#     print(‘子进程[%s]运行。。。。‘ %current_process().name)
#     time.sleep(2)
#
# if __name__ == ‘__main__‘:
#     p1=Process(target=task,name=‘子进程1‘)
#     p1.start()
#
#     # print(p1.is_alive())
#     # p1.join()
#     # print(p1.is_alive())
#
#     p1.terminate()  # 终止进程,应用程序给操作系统发送信号,让操作系统把这个子程序干掉
#                     # 至于多久能干死,在于操作系统什么时候执行这个指令
#     time.sleep(1)
#     print(p1.is_alive())  # 查看子进程是否存在,有返回值. True则存在,False则不存在
#     print(‘主‘)
进程对象的方法与属性
孤儿进程: 无害,会被孤儿院((linux的孤儿院)init)回收
僵尸进程: 正常情况下无害(会掉用wait()方法进行回收操作), 在父进程无限循环,且不被回收的情况下会无限制的生成子进程从而占用大量的操作系统资源
   当操作系统被大量僵尸进程占满内存后,操作系统就无法在启动其他的程序
守护进程
技术分享图片
‘‘‘
1、守护进程
    守护进程其实就是一个“子进程”
    守护=》伴随
    守护进程会伴随主进程的代码运行完毕后而死掉

2、为何用守护进程
    关键字就两个:
        进程:
            当父进程需要将一个任务并发出去执行,需要将该任务放到一个子进程里
        守护:
            当该子进程内的代码在父进程代码运行完毕后就没有存在的意义了,就应该
            将该子进程设置为守护进程,会在父进程代码结束后死掉
‘‘‘

# from multiprocessing import Process
# import time,os
#
# def task(name):
#     print(‘%s is running‘ %name)
#     time.sleep(3)
#
# if __name__ == ‘__main__‘:
#     p1=Process(target=task,args=(‘守护进程‘,))
#     p2=Process(target=task,args=(‘正常的子进程‘,))
#
#     p1.daemon = True # 一定要放到p.start()之前
#     p1.start()
#     p2.start()
#
#     print(‘主‘)



#主进程代码运行完毕,守护进程就会结束
from multiprocessing import Process
import time
def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(3)
    print("end456")

if __name__ == __main__:
    p1=Process(target=foo)
    p2=Process(target=bar)

    p1.daemon=True
    p1.start()
    p2.start()
    print("main-------")

    ‘‘‘
    main-------
    456
    enn456
    ‘‘‘


    ‘‘‘
    main-------
    123
    456
    enn456
    ‘‘‘

    ‘‘‘
    123
    main-------
    456
    end456
    ‘‘‘
守护进程

互斥锁

技术分享图片
#互斥锁:可以将要执行任务的部分代码(只涉及到修改共享数据的代码)变成串行
#join:是要执行任务的所有代码整体串行
from multiprocessing import Process,Lock    #  Lock 互斥锁模块
import json
import os
import time
import random

def check():
    time.sleep(1) # 模拟网路延迟
    with open(db.txt,rt,encoding=utf-8) as f:
        dic=json.load(f)
    print(%s 查看到剩余票数 [%s] %(os.getpid(),dic[count]))

def get():
    with open(db.txt,rt,encoding=utf-8) as f:
        dic=json.load(f)
    time.sleep(2)
    if dic[count] > 0:
        # 有票
        dic[count]-=1
        time.sleep(random.randint(1,3))
        with open(db.txt,wt,encoding=utf-8) as f:
            json.dump(dic,f)
        print(%s 购票成功 %os.getpid())
    else:
        print(%s 没有余票 %os.getpid())


def task(mutex):
    # 查票
    check()

    #购票
    mutex.acquire() # 互斥锁不能连续的acquire,必须是release以后才能重新acquire
    get()
    mutex.release()  # 关闭互斥锁



    # with mutex:   # 开启与关闭互斥锁一种简单的写法
    #     get()

if __name__ == __main__:
    mutex=Lock()
    for i in  range(10):
        p=Process(target=task,args=(mutex,))
        p.start()
        # p.join()
互斥锁

IPC机制

技术分享图片
#IPC:进程间通信,有两种实现方式
#1、pipe:管道
#2、queue:pipe+锁


from multiprocessing import Queue


# q=Queue(3) #先进先出
#注意:
#1、队列占用的是内存空间
#2、不应该往队列中放大数据,应该只存放数据量较小的消息
# 掌握的
q.put(first)
q.put({k:sencond})
q.put([third,])
# q.put(4)

print(q.get())
print(q.get())
print(q.get())
print(q.get())
#

#了解的
# q=Queue(3) #先进先出
# q.put(‘first‘,block=True,timeout=3)
# q.put({‘k‘:‘sencond‘},block=True,timeout=3)
# q.put([‘third‘,],block=True,timeout=3)
# print(‘===>‘)
# # q.put(4,block=True,timeout=3)
#
#
# print(q.get(block=True,timeout=3))
# print(q.get(block=True,timeout=3))
# print(q.get(block=True,timeout=3))
# print(q.get(block=True,timeout=3))



# q=Queue(3) #先进先出
# q.put(‘first‘,block=False,)
# q.put({‘k‘:‘sencond‘},block=False,)
# q.put([‘third‘,],block=False,)
# print(‘===>‘)
# # q.put(4,block=False,) # 队列满了直接抛出异常,不会阻塞
#
# print(q.get(block=False))
# print(q.get(block=False))
# print(q.get(block=False))
# print(‘get over‘)
# print(q.get(block=False))
#


q=Queue(3) #先进先出

q.put_nowait(first) #q.put(‘first‘,block=False,)
q.put_nowait(2)
q.put_nowait(3)
# q.put_nowait(4)  # 队列满了不会等待,直接抛出异常

print(q.get_nowait())
print(q.get_nowait())
print(q.get_nowait())
print(q.get_nowait())  # 队列里没有数据了不会等待,直接抛出异常
IPC

生产者与消费者模型

技术分享图片
‘‘‘
1 什么是生产者消费者模型
    生产者:比喻的是程序中负责产生数据的任务
    消费者:比喻的是程序中负责处理数据的任务

    生产者->共享的介质(队列)<-消费者

2 为何用
    实现了生产者与消费者的解耦和,生产者可以不停地生产,消费者也可以不停地消费
    从而平衡了生产者的生产能力与消费者消费能力,提升了程序整体运行的效率

    什么时候用?
        当我们的程序中存在明显的两类任务,一类负责产生数据,另外一类负责处理数据
        此时就应该考虑使用生产者消费者模型来提升程序的效率


‘‘‘
# from multiprocessing import Queue,Process
# import time
# import os
# import random
#
# def producer(q):
#     for i in range(10):
#         res=‘包子%s‘ %i
#         time.sleep(random.randint(1,3))
#         # 往队列里丢
#         q.put(res)
#         print(‘33[45m%s 生产了 %s[0m‘ %(os.getpid(),res))
#     q.put(None)
#
# def consumer(q):
#     while True:
#         #从队列里取走
#         res=q.get()
#         if res is None:break
#         time.sleep(random.randint(1,3))
#         print(‘33[46m%s 吃了 %s[0m‘ %(os.getpid(),res))
#
# if __name__ == ‘__main__‘:
#     q=Queue()
#     # 生产者们
#     p1=Process(target=producer,args=(q,))
#     # 消费者们
#     c1=Process(target=consumer,args=(q,))
#
#     p1.start()
#     c1.start()
#
#     print(‘主‘)





# from multiprocessing import Queue,Process
# import time
# import os
# import random
#
# def producer(name,food,q):
#     for i in range(3):
#         res=‘%s%s‘ %(food,i)
#         time.sleep(random.randint(1,3))
#         # 往队列里丢
#         q.put(res)
#         print(‘33[45m%s 生产了 %s33[0m‘ %(name,res))
#     # q.put(None)
#
# def consumer(name,q):
#     while True:
#         #从队列里取走
#         res=q.get()
#         if res is None:break
#         time.sleep(random.randint(1,3))
#         print(‘33[46m%s 吃了 %s33[0m‘ %(name,res))
#
# if __name__ == ‘__main__‘:
#     q=Queue()
#     # 生产者们
#     p1=Process(target=producer,args=(‘egon‘,‘包子‘,q,))
#     p2=Process(target=producer,args=(‘杨军‘,‘泔水‘,q,))
#     p3=Process(target=producer,args=(‘猴老师‘,‘翔‘,q,))
#     # 消费者们
#     c1=Process(target=consumer,args=(‘Alex‘,q,))
#     c2=Process(target=consumer,args=(‘wupeiqidsb‘,q,))
#
#     p1.start()
#     p2.start()
#     p3.start()
#     c1.start()
#     c2.start()
#
#     p1.join()
#     p2.join()
#     p3.join()
#     # 在p1p2p3都结束后,才应该往队列里放结束信号,有几个消费者就应该放几个None
#     q.put(None)
#     q.put(None)

    # print(‘主‘)


from multiprocessing import JoinableQueue,Process
import time
import os
import random

def producer(name,food,q):
    for i in range(3):
        res=%s%s %(food,i)
        time.sleep(random.randint(1,3))
        # 往队列里丢
        q.put(res)
        print(33[45m%s 生产了 %s33[0m %(name,res))
    # q.put(None)

def consumer(name,q):
    while True:
        #从队列里取走
        res=q.get()
        if res is None:break
        time.sleep(random.randint(1,3))
        print(33[46m%s 吃了 %s33[0m %(name,res))
        q.task_done()  # 对主进程说我拿了一个数据走了

if __name__ == __main__:
    q=JoinableQueue()
    # 生产者们
    p1=Process(target=producer,args=(egon,包子,q,))
    p2=Process(target=producer,args=(杨军,泔水,q,))
    p3=Process(target=producer,args=(猴老师,,q,))
    # 消费者们
    c1=Process(target=consumer,args=(Alex,q,))
    c2=Process(target=consumer,args=(wupeiqidsb,q,))
    c1.daemon=True
    c2.daemon=True  # 把消费者变成守护进程

    p1.start()
    p2.start()
    p3.start()
    c1.start()
    c2.start()

    p1.join()
    p2.join()
    p3.join()

    q.join() #等待队列被取干净
    # q.join() 结束意味着
    # 主进程的代码运行完毕--->(生产者运行完毕)+队列中的数据也被取干净了->消费者没有存在的意义

    # print(‘主‘)
生产者与消费者模型

 





以上是关于开启子进程的两种方式,孤儿进程与僵尸进程,守护进程,互斥锁,IPC机制,生产者与消费者模型的主要内容,如果未能解决你的问题,请参考以下文章

僵尸 孤儿 守护 进程的理解

并发编程

并发编程

戏说守护僵尸孤儿进程

菜鸟随笔---三种进程学习.孤儿进程.僵尸进程.守护进程

第7章 进程关系_守护孤儿和僵尸进程