DAY 33 进程理论与进程方法

一.进程理论

  1.什么是进程,与程序的区别

   程序是一堆代码,而进程是指正在运行的程序

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

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

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

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

  3.阻塞和非阻塞:针对程序运行的状态

   阻塞:遇到IO操作>>> 阻塞态

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

二.开启进程的两种方式

  1.直接通过Process类创建进程

  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__':

    p = Process(target = task,args = ('egon',)) # 实例化出一个对象

    p.start() # 告诉操作系统创建一个进程

    print('主') 

  2.通过自定义类继承Process类来创建进程

  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(3)

      print('%s is over' % 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)

  # join的作用仅仅只是让主进程等待子进程的结束,不会影响其他子进程的运行

四.进程之间内存隔离

  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) # 100

五.进程对象的其他相关方法

  from multiprocessing import Process, current_process

  import time

  import os

  

  def task():

    print('%s is running' % os,getpid()) # % current_process().pid

    time.sleep(3)

    print('%s is over' % os.getppid()) # 获取父进程PID

  if __name__ == '__main__':

    p = Process(target=task)

    p.start()

    # p.terminate() # 杀死子进程

    # print(p.is_alive()) # 判断子进程是否存活

    print('主')

六.僵尸进程与孤儿进程

  僵尸进程:两种情况下会回收子进程的pid等信息

    1.父进程正常结束

    2.join方法

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

    linux下: init进程用来回收孤儿进程所占用的资源

    ps aux |grep 'Z'

七.守护进程

  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('主进程死亡') # 守护进程无论什么状态都直接死亡

八.互斥锁(千万不能随意去使用)

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

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()

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

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

  加锁会将并发变成串行

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

  

原文地址:https://www.cnblogs.com/majingjie/p/10819919.html