创建进程及进程相关方法

昨日内容

基于TCP的大文件 上传 # 注意是上传
客户端:
1、制作字典报头
   2、发送报头
   3、发送字典
   4、发送真实数据
服务端:
1、接收报头,从报头中获取字典长度
   2、获取字典长度
   3、接收字典,从字典中获取真实数据的长度
   4、接收真实数据

socketserver模块:  # (劳保)
使TCP能够实现并发

UDP协议:
1、不需要建立连接
 2、服务端不启动也可以发送数据
 3、UDP协议不存在粘包问题
 4、可以实现并发
 
操作系统发展史:
1、穿孔卡带
 2、磁带
 3、批处理
目的:都是为了提高CPU利用率
 
多道技术:
空间上的复用:
多个程序共用一台计算机
 时间上的复用:
(洗衣服,做饭,烧水)

CPU会在多个程序中来回切换的执行程序
CPU在两种情况下会切换到别的程序:
1、一个程序占用CPU时间过长
 2、遇到IO行为
 
并发:看起来像同时运行就是并发
并行:真正的同时运行

今日内容

1、进程理论
2、同步和异步 | 阻塞与非阻塞
3、开启进程的两种方式(***)
4、进程对象的join方法(***)
5、进程之间内存隔离(***)
6、进程对象其他相关方法
7、僵尸进程与孤儿进程
8、守护进程
9、互斥锁(***) 锁千万不要随意去用

一、进程理论

进程:正在运行的程序
进程是一个实体,每一个进程都有其专有的名称空间
 
# 进程三态转换图

二、同步和异步 | 阻塞与非阻塞

这是两对 独立 不同 的概念

同步和异步:针对任务的提交方式
同步:提交任务之后,原地等待任务返回的结果
异步:提交任务之后,不等待任务的返回结果,直接运行下一行代码

阻塞与非阻塞:针对程序的运行状态
阻塞:遇到IO操作 >>> 阻塞态  # 进程三态状态转换图
非阻塞:就绪或者运行态 >>> 就绪态,运行态

三、开启进程的两种方式

方法一:
from multiprocessing import Process
import time

def task(name):
 print('%s is running' % name)
 time.sleep(3)
 print('%s is done' % name)
 
 
# 在windows系统中,创建进程会将代码以模块的方式从头到尾运行一遍
# 所以一定要写在main下面
if __name__ == '__main__':
 # 注意 targe = task() 这后面的函数加括号意思就是优先级最高,立刻执行
 p1 = Process(target=task, args=('egon', ))  # 实例化Process对象
 p1.start()  # 告诉操作系统创建一个进程
 print('主程序')
 
 
方法二:
from multiprocessing import Process
import time

class Myprocess(Process):  # 重写Proess中的task方法
 def __init__(self, name):
   super().__init__(slef):
   self.name = name
 
 # 重写的类中必须定义一个run方法
def run(self):  # 既上一个方法中的 task 方法
   print('%s is runnning' % self.name)
   time.sleep(3)
   print('%s is done' % self.name)

if __name__ == '__main__':
 p1 = Myprocess('egon')  # 实例化重写方法后的对象
 p1.start()  # 告诉操作系统创建一个进程
 print('主程序')

四、进程对象的join方法

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__':
 p1 = Process(target=task, args=('egon', ))
 p1.start()  # 告诉操作系统创建一个进程
 print('主程序')
run==>
主程序
egon is running
egon is done
 
# 以上的代码会出现 子程序还没有运行结束 而 主程序已经结束了
# 有时,主程序需要接收子程序结束时的返回值,那么就需要等子进程结束后在运行主程序
# 使用join方法,既:
if __name__ == '__main__':
 p1 = Process(target=task, args=('egon', ))
 p1.start()  # 告诉操作系统创建一个进程
 p1.join()  # 意为等待程序p1运行结束,否则堵塞在这,同时join方法会清理子程序的pid地址和其他数据
 print('主程序')
run==>
egon is running
egon is done
主程序

五 、进程之间内存隔离

测试代码:
from multiprocessing import Process

num = 1
def task():
 gobal num
 num = 100
 
if __name__ == '__main__':
 p1 = Process(target=task)
 p1.start()
 p1.join()
 print('主程序', x)
run==>
主程序 1

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

from multiprocessing import Process, current_process
import time, os

def task():
 # 获取pid(进程地址)的方法一:current_process().pid
 print('%s is running' % current_process().pid)
 time.sleep(3)
 # 获取pid(进程地址)的方法二:os.getpid()
 print('%s is done'  % os.getpid())

if __name__ == '__main__':
 p1 = Process(target=tast)
 p1.start()
 # p1.terminate() # 杀死子进程
 # time.dleep(0.1) # 给操作系统关闭子程序的时间
 # print(p1.is_alive())
 print('主程序')
run==>
主程序
1768 is running
1768 is done

七、僵尸进程与孤儿进程

两种情况下会回收子进程的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('皇帝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:  # 余票信息在文件'info'中
       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()

 

posted @ 2019-05-06 16:47  输诚  阅读(213)  评论(0编辑  收藏  举报