python多进程笔记1 - 初步认知:进程,并发并行,算法调度,阻塞非阻塞,异步与同步,锁

20171104 python多进程编程
=====================================================================
积累:
ps -ef >1.txt 重定向到1.txt文件当中去
vim编辑器:
hjkl光标的左移,下移,上移,右移
gg移动到文档的最上方
ctrl+3 光标指向该位置上方的相同的字段
=====================================================================
1.程序和进程
程序:存储在电子设备上0与1有序组合;
进程:程序在操作系统(OS)中运行的一个抽象;
      抽象是一种近似,一种简化,帮助我们认识事物和使用事物
程序与进程的关系:
      一对一,一对多,  (有道云笔记,谷歌浏览器)
      多对一,多对多,  (..........)
实例:
在ipyhton交互环境中:
In [1]: 1/3
Out[1]: 0.3333333333333333


In [2]: 0.3333333333333333
Out[2]: 0.3333333333333333


In [3]: 0.3333333333333333*3
Out[3]: 1.0


In [4]: 3+1e20
Out[4]: 1e+20


In [5]: 3+1e20-1e20
Out[5]: 0.0


In [6]: 3+(1e20-1e20)
Out[6]: 3.0       说明:python不满足结合律
意义:在做数据计算时,先(绝对值大的数据)对精度几近相似的数据进行计算
=====================================================================
2.对程序、进程、和线程进行一种抽象类似的近似
概念:
OS操作系统:公司
cpu,I/O:公司的资源
进程:公司的部门;做各种事情;部门有自己的办公区;有自己的厕所,自己的餐    
      厅,自己的健身房;部门要有人(进程创建以后一定有线程)
线程:部门的人;来干活的
锁:部门的厕所那把锁;健身房的那把锁;作用-限流;资源有限,需要多资源进行管 
    理;管理资源就需要加锁;有锁就必然会有钥匙


3.进程:OS对程序执行的一次抽象;
A:进程的组成:
    数据段,代码段,进程控制块(PCB)-进程信息的控制块,公司裁员
    进程控制块:
     (1)进程的标识符号 pid,name
     (2)进程的调度信息(进程的状态,进程的优先级,进程的关系)
     (3)进程的控制信息(资源清单,信号量,互斥量,锁的信息,虚拟的地址等)    
     (4)处理机的信息(通用寄存器,指令计数器等)


实验:
ps   #linux系统查看进程的命令
ps  -aux     #进程快照
top/htop          #linux系统进程动态显示
linux系统中的NI:linux下的进程优先级 -20 - 19
ps linux下查看进程的命令
ps linux -aux 进程快照
top  进程动态显示


进程的主要特征:
    动态性,独立性,并发性,结构性




B.几种特殊的进程:
孤儿进程:父进程创建子进程,被杀或者他杀;
僵尸进程:父进程创建子进程,子进程被杀或者自杀,父进程没有上报(系统,系统依旧分配资源,导致多余资源无法回收)


=====================================================================
3.进程中的相关名词:
进程状态:
    就绪、执行、等待/阻塞(新建、终止);
    注意:进程在阻塞状态时,必须先进入就绪状态,然后才能进入执行状态


进程调度:
    操作系统会合理为系统中进程分配资源,供其运行;
    调度算法有:时间片轮转调度;基于优先级的抢占式调度


多任务:多个软件同时运行,完成不同的功能


并发与并行:
并发:
同一时间点,多个进程同时在跑,但在及其微小的时间中看来,还是存在时间上的执行顺序的(一个部门做三件事情也是有先后顺序的);
并行:
多个核,在同一时间点,在物理意义上是真生存在多个进程同时运行;实际上只有多核操作系统,才有真正的并行(三个部门同时做三件事情)。


阻塞与非阻塞:
阻塞:进程一直在等待运行;
非阻塞:进程离开去做其他的事情


异步与同步:
同步:只有自己同时做几件事情
异步:自己买东西查东西的同时,卖家同时给予反馈


关于死锁:
死锁:进程A、进程B需要都拿到资源1,2才能执行,但是现在进程A进程占用资源1,等待资源2的释放;进程B占用资源2,等待资源1的释放,两个进程互斥,于是发生死锁
解决死锁:
(1)避免互斥 避免资源被一个进程使用;缺点,和资源本身的性质有关系;
(2)资源获取的原子性,保证所有的资源都拿到,否则都不要;缺点,效率低,当进程B只需要资源1时,也必须将资源2取出;
(3)让资源有序化(资源获取排队),缺点,效率低,例如银行家算法
上面3个方法在设计上尝试避免死锁发生;
(4)请求与保持条件,比如timeout,调度算法处理;缺点,需要确定谁放手;
上面这个方法是指在发生时进行补救
注:原子性表示一个操作序列就像一个操作一样不被打断,而不像一个操作序列一样中间容许被打断。


multiprocessing包:
python跨平台的多进程管理宝,实现本地和远程并发
支持windos、linux平台


帮助(交互环境下) 
import multiprocessing
help(multiprocessing.Process)
help(fork)
单核:一个时刻只能执行一个进程的一条指令
资源:时间片


Python daemon进程:
1.后台进程;
2.主进程一结束,子进程就跟着结束(因为该属性,慎用daemon);
3.写在start之前
4.可以随时被杀死


数据结构:
队列:FIFO(First In First Out) 先进先出  例:排队买票(两个门)
栈:LIFO(Last In First Out) 先进后出  例:电梯(只有一个门)
优先队列:priority queue


进程调度:
时间片:就绪等待执行等待的东西(轮到谁执行谁);
优先级:自定义设置执行顺序
=====================================================================
程序实例(1):演示僵尸进程,解释见下方文件
from multiprocessing import Process
import time
def t1(interval):
    for i in range(interval):     
    # while True:
        time.sleep(1)   
        print('child  '+time.ctime())  
if __name__ == '__main__':  
    P = Process(target=t1,args=(5,))
    # P.daemon = True   
    P.start()
    # P.join()      
    time.sleep(2)   
    print('main process')  
    while True:
        # p.terminate()   
        time.sleep(2)   
        print('mian   '+time.ctime())  
========================================================================
程序实例(2):#演示子进程一定会被父进程接管,解释键下方文件
import os
import time
pid = os.fork()    
if pid < 0:
    print('fork error')
elif pid == 0:
    # time.sleep(1)
    print('child id %d,parent id %d' % (os.getpid(),os.getppid()))     
else:
    print('parent id %d,child id %d' % (os.getpid(),pid))
========================================================================
详细解释:程序实例(1):演示僵尸进程,解释见下方文件


from multiprocessing import Process  #此句已经是主进程
import time
def t1(interval):
    for i in range(interval):  #设置子进程的执行次数
    # while True:         #设置死循环 子进程反复执行
        time.sleep(1)   #睡1秒
        print('child  '+time.ctime())  #打印时间,按某种格式打印时间
if __name__ == '__main__':  #如果存在父子进程关系,父进程会等子进程,等子进程执行结束,父进程再结束
    P = Process(target=t1,args=(5,))#创立进程,后面是创建元组,生成可迭代对象使子进程执行5次
    # P.daemon = True   #守卫进程语句:一旦主进程结束,子进程立刻结束,放在start()之前
    P.start()
    # P.join()  #等待进程语句,父进程一定会等待子进程,使得守卫语句失效,变成正常的父子进程关系:父等待子进程结束
    time.sleep(2)   #睡眠状态 兄弟关系的进程会抢占资源谁执行都不一定
    print('main process')  # 主进程再这里已经结束,因为父子进程关系,父进程会等待子进程执行结束,不会在这这里结束
    while True:    #子进程在这里开始执行
        # p.terminate()   #结束进程语句  子进程被杀成为僵尸进程,但是系统没有收回资源
        time.sleep(2)   
        print('mian   '+time.ctime())  


#tarena@tedu:~/aid1709$ ipython3 1104.py
child  Sat Nov  4 19:54:04 2017
main process
child  Sat Nov  4 19:54:05 2017
child  Sat Nov  4 19:54:06 2017
mian   Sat Nov  4 19:54:07 2017
child  Sat Nov  4 19:54:07 2017
child  Sat Nov  4 19:54:08 2017
mian   Sat Nov  4 19:54:09 2017
mian   Sat Nov  4 19:54:11 2017
mian   Sat Nov  4 19:54:13 2017
========================================================================
详细解释:程序实例(2):#演示子进程一定会被父进程接管,解释键下方文件


import os   #主进程已经开始
import time
pid = os.fork() #fork为父进程创建了子进程,返回两个值!!创建时后立刻抛弃父子关系,成为兄弟进程,两者并行执行,父进程不会等待子进程结束以后再结束
if pid < 0:
    print('fork error')
elif pid == 0:  # Return 0 to child process, pid = os.fork(),如果是子进程返回0 
    time.sleep(1) #子进程睡眠,成为孤儿进程,睡醒之后由系统接管,系统成为其父进程;1秒睡眠时间对于cpu而言时间很长,两个进程并发执行
    print('child id %d,parent id %d' % (os.getpid(),os.getppid()))     #子进程被接管
else:
    print('parent id %d,child id %d' % (os.getpid(),pid))#两者并行执行,谁先执行不一定


# tarena@tedu:~/aid1709$ python3 11042.py
# parent id 9564,child id 9565    #子进程睡眠,父进程进入else语句
# tarena@tedu:~/aid1709$ child id 9565,parent id 1873  子进程睡醒,没有父进程,被系统接管,生成新的父进程
# 父进程结束 子进程由操作系统接管  ps -aux |grep 1751
# fork()
#     Fork a child process.
#     Return 0 to child process and PID of child to parent process.


========================================================================
作业:
(1)设置优先级1-20,做一个模拟os的调度程序:某一时刻,四个进程:
Watch TV:          random优先级  import rnadom
Listen to music:   random优先级
Print Doc:         4
Write Doc:         4
创建队列,信息放进队列,模拟队列的调度(观察取数情况,验证时间片)
(2)多进程定期器:每一个小时,你的定时器提示你:不要coding,休息一下吧!
提示的同时显示当前进程的pid,name,os模块设置优先级
(3)通过一个进程池实现
文件夹下大量文件拷贝;至少500个文件,有方法证明你的拷贝的文件是ok的
预期过程:
input 四个进程的信息
output 打印出四个进程谁先输入输出(查看是时间片还是优先级调度)
多进程在队列中获取信息,发生阻塞时等,或者timeout(2秒超时退出),或者get_nowait()(立刻取,没有就不处理,直接退出)


提示:
递归
p = queue.PriorityQueue() 创建队列 
help(p.get)
help(queue.PriorityQueue)


|  get(self, block=True, timeout=None)
 |      Remove and return an item from the queue.
 |      
 |      If optional args 'block' is true and 'timeout' is None (the default),
 |      block if necessary until an item is available. If 'timeout' is
 |      a non-negative number, it blocks at most 'timeout' seconds and raises
 |      the Empty exception if no item was available within that time.
 |      Otherwise ('block' is false), return an item if one is immediately
 |      available, else raise the Empty exception ('timeout' is ignored
 |      in that case).
 |  
 |  get_nowait(self)
 |      Remove and return an item from the queue without blocking.
 |      
 |      Only get an item if one is immediately available. Otherwise
 |      raise the Empty exception.
help(p.get_nowait)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值