进程

一、进程理论
1、程序和进程的区别
程序:一堆代码
进程:正在运行的程序
进程是一个实体,每一个进程都有它自己独立的内存空间
2、同步和异步
同步:提交任务之后原地等待任务的返回结果,期间不做任何事
异步:提交任务之后,不等待任务的返回结果,执行运行下一行代码
3、阻塞与非阻塞:针对程序运行的状态
阻塞:遇到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',))
    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 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)
四、进程之间数据隔离
# 记住进程与进程之间数据是隔离的
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)
五、进程对象其他相关方法
from multiprocessing import Process,current_process
import time
import os


def task():
    print('%s is running'%os.getpid())  # current_process().pid 获取自己的pid号
    time.sleep(3)
    print('%s is over'%os.getppid())    # 获取父进程pid号


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孤儿福利院:用来回收孤儿进程所占用的资源
代码实现: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=('子进程',))
    p.daemon = True    # 必须在p.start开启之前命令之前声明
    p.start()
    time.sleep(1)
    print('主进程正在死亡')
八、互斥锁
1、特点:
牺牲了效率但是保证了数据的安全
锁一定要在主进程中创建,给子进程用
解决多个进程操作同一份数据,造成数据不安全的情况
加锁会将并发变成串行
锁通常用在对数据操作的部分,并不是对进程全程加锁
mutex.acquire() # 抢锁 一把锁不能同时被多个人使用
buy(i)
mutex.release() # 释放锁
2、实例:
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查询余票:%s'%(i,data.get('ticket')))


def buy(i):
    with open('info','r',encoding='utf-8')as f:
        data = json.load(f)
    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)
    time.sleep(random.randint(1, 3))   # 模拟网络延迟
    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()

 

posted @ 2019-05-06 16:06  ymg-颜  阅读(122)  评论(0编辑  收藏  举报