• 并发编程之进程


    一 、进程理论

        程序:一堆代码

        进程:正在运行的程序

        进程是一个实体。每一个进程都有它自己独立的内存空间

    同步和异步:针对任务的提交方式

          同步:提交任务之后原地等待任务的返回结果,期间不做任何事

          异步:提交任务之后,不等待任务的返回结果,执行运行下一行代码

    阻塞与非阻塞:针对程序运行的状态

          阻塞:遇到 io 操作     》》》阻塞态

          非阻塞:就绪或者运行态   》》》就绪态,运行态

    二 、开启进程的两种方式(***)

        

        1、

    from multiprocessing import Process
    import time

    def task(name):
    print('%s is running'%name)
    time.sleep(3)
    print('%s is over'%name)


    # 注意,在windows系统中,创建进程会将代码以模块的方式从头到尾加载一遍
    # 一定要写在if __name__ == '__main__':代码块里面
    # 强调:函数名一旦加括号,执行优先级最高,立刻执行
    if __name__ == '__main__':
    p1 = Process(target=task,args=('egon',)) # 这一句话只是实例化了一个Process对象
    p1.start() # 告诉操作系统创建一个进程
    print('这是一个父程序')

        2、

    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(1)
    print('%s is end'%self.name)

    if __name__ == '__main__':
    obj = MyProcess('egon')
    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__':
    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 i in p_list:
    i.join() # 主进程等待子进程结束 才继续运行
       print('这是一个主程序',time.time()-start_time)

    四 、 进程之间内存隔离(***)

    from multiprocessing import Process

    x = 100
    def task():
    global x
    x =1

    if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()
    print('这是主程序',x)

    进程是程序的执行单位,线程是CPU的执行单位。程序之间的数据是互相独立运行的,因此进程运行的时候并不会影响其他进程,导致进程混乱。

    五 、进程对象其他相关方法

    from multiprocessing import Process,current_process
    import time
    import os

    def task():
    print('%s is running'%os.getpid())
    time.sleep(3)
    print('%s is over'%os.getppid())


    if __name__ == '__main__':
    p1 = Process(target=task)
    p1.start()
    # p1.terminate() # 杀死子进程
    # time.sleep(0.1)
    # print(p1.is_alive()) # 判断子进程是否存活
    print('主')

    六 、僵尸进程与孤儿进程

            两种情况下会回收子进程的 pid 等消息

                1 、父进程正常结束

                2 、join 方法

            孤儿进程:父进程意外死亡

            Linux下:init 孤儿福利院:用来回收孤儿进程所占用的资源

    七 、守护进程:父进程结束了子进程必须也跟着结束

    from multiprocessing import Process
    import time

    def task(name):
    print('%s 正活着'%name)
    time.sleep(3)
    print('%s 正常死亡'%name)


    if __name__ == '__main__':
    p = Process(target=task,args=('egon总管',))
    p.daemon = True # 必须在p.start开启进程命令之前声明
    p.start()
    print('皇帝jason正在死亡')

    八 、互斥锁(***)    千万不要随意使用,意思就是说能不用就尽量不用

      牺牲了效率但是保证了数据的安全

      锁一定要在主进程中创建,给子进程去用

      解决多个进程操作同一份数据,造成数据不安全的情况

      加锁会将并发变成串行

      锁通常用在对数据操作的部分,并不是对进程全程加锁

       

      mutex.acquire() # 抢锁 一把锁不能同时被多个人使用,没有抢到的人,就一直等待锁释放
      buy(i)
      mutex.release() # 释放锁

    关于抢票延迟的例子  

    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查询余票为0"%i)


    def run(i,mutex):
    search(i)
    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()
  • 相关阅读:
    26. 删除排序数组中的重复项
    巧记“指针数组”与“数组指针”
    在 VC 下清空键盘缓冲区的方法
    负数、取模与取余
    任意键开始、暂停
    int 越界处理
    防闪屏批量绘图
    VC 下如何正确的创建及管理项目
    CSDN博客步骤:
    61 扑克牌中的顺子
  • 原文地址:https://www.cnblogs.com/SlookUp/p/10820648.html
Copyright © 2020-2023  润新知