zoukankan      html  css  js  c++  java
  • 进程

    一.进程的概念:

    狭义定义:进程是正在运行的程序的实例

    广义定义:是一个具有独立功能的程序关于某个数据集合的一次运动活动,它是操作系统动态执行的基本单元,在传统的操作系统中,进程是基本的分配单元,也是基本的执行单元.

    二.进程的组成: 

    代码段,数据段,PCB(代码控制块)

    三.进程的三个基本状态:

    就绪状态:获得了除CPU以外所有必要的资源,只要获得处理机便可立即执行

    执行状态:获得了包括cup和所有必要的资源,处在正在执行的状态

    阻塞状态:因为各种原因,导致进程放弃了cpu,导致进程无法继续进行,此时进程在内存中

    四.进程的并行和并发:

    并行 : 并行是指两者同时执行,比如有两条车道,在某一个时间点,两条车道上都有车在跑;(资源够用,比如三个线程,四核的CPU )
    
    并发 : 并发是指资源有限的情况下,两者交替轮流使用资源,比如只有一条车道(单核CPU资源),那么就是A车先走,在某个时刻A车退出把道路让给B走,B走完继续给A ,交替使用,目的是提高效率。
    
    区别:
    
    并行是从微观上,也就是在一个精确的时间片刻,有不同的程序在执行,这就要求必须有多个处理器。
    并发是从宏观上,在一个时间段上可以看出是同时执行的,比如一个服务器同时处理多个session。
    
    注意:早期单核CPU时候,对于进程也是微观上串行(站在cpu角度看),宏观上并行(站在人的角度看就是同时有很多程序在执行)。

    五.同步异步:

    同步:所谓同步就是一个任务的完成需要依赖另外一个任务是,只要等待被依赖的任务完成后,依赖的任务才算完成,只是一种可靠的任务序列,要么成功都成功,失败都失败,两个任务的状态可以保持一致.

    异步:是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了,至于被依赖的任务是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列.

     六.阻塞,非阻塞

    阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的

    七.进程的两种开启方式:

    from multiprocessing import process
    def func(n):
        print(123)
    if __name__ = '__main__':
        p = Process(target = func,args(1,))
        p.start()
        print(345)
    
    target:是子进程要执行的任务
    args:是父进程给子进程传递的参数
    os.getpid() :获取当前进程的pid号
    os.getppid():获取当前进程的父进程的pid号
    from multiprocessing import process
    class Myprocess(Process):
        def __init__ (self):
            super().__init__()
        def run (self):
            print(123)
    if __name__ = '__main__':
        p = Myprocess()
        p.start()

    八.进程的常用方法:

    Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)
    
    强调:
    1. 需要使用关键字的方式来指定参数
    2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
    
    参数介绍:
    group参数未使用,值始终为None
    target表示调用对象,即子进程要执行的任务
    args表示调用对象的位置参数元组,args=(1,2,'egon',)
    kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
    name为子进程的名称
    参数介绍
    p.start():启动进程,并调用该子进程中的p.run() 
    p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法  
    p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
    p.is_alive():如果p仍然运行,返回True
    p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程  
    方法介绍
    p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
    p.name:进程的名称
    p.pid:进程的pid
    p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
    p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)
    属性介绍
    在Windows操作系统中由于没有fork(linux操作系统中创建进程的机制),在创建子进程的时候会自动 import 启动它的这个文件,而在 import 的时候又执行了整个文件。因此如果将process()直接写在文件中就会无限递归创建子进程报错。所以必须把创建子进程的部分使用if __name__ ==‘__main__’ 判断保护起来,import 的时候  ,就不会递归运行了。
    在windows中使用process模块的注意事项

    ps:守护(daemon)进程的两个特点:

      守护进程会随着父进程的结束而结束

      守护进程不能再创建子进程

    九.锁机制 

    from multiprocessing import Process,Value,Lock
    import time
    
    
    def get_money(num,l):# 取钱
        l.acquire()# 拿走钥匙,锁上门,不允许其他人进屋
        for i in range(100):
            num.value -= 1
            print(num.value)
            time.sleep(0.01)
        l.release()# 还钥匙,打开门,允许其他人进屋
    
    def put_money(num,l):# 存钱
        l.acquire()
        for i in range(100):
            num.value += 1
            print(num.value)
            time.sleep(0.01)
        l.release()
    
    if __name__ == '__main__':
        num = Value('i',100)
        l = Lock()
        p = Process(target=get_money,args=(num,l))
        p.start()
        p1 = Process(target=put_money, args=(num,l))
        p1.start()
        p.join()
        p1.join()
        print(num.value)

    十.信号机制:

    from multiprocessing import Process,Semaphore
    import time
    import random
    
    def func(i,sem):
        sem.acquire()
        print('第%s个人进入小黑屋,拿了钥匙锁上门' % i)
        time.sleep(random.randint(3,5))
        print('第%s个人出去小黑屋,还了钥匙打开门' % i)
        sem.release()
    
    if __name__ == '__main__':
        sem = Semaphore(5)# 初始化了一把锁5把钥匙,也就是说允许5个人同时进入小黑屋
        # 之后其他人必须等待,等有人从小黑屋出来,还了钥匙,才能允许后边的人进入
        for i in range(20):
            p = Process(target=func,args=(i,sem,))
            p.start()
    sem = Semaphore(n)
    n:是指初始化一把锁配几把钥匙,一个int类型
    l.acquire:拿钥匙,锁门
    l.release:拿钥匙,开门
    信号量机制比锁机制多了一个计数器,这个计数器是用来记录当前剩余几把钥匙的,当计数器为0时,表示没有钥匙了,此时acquire()处于阻塞.
    对于计数器来说,没acquire一次,技术器就减1,release一次,技术器就加1

    十一.事件机制

    e = Event()
    e.set() 将is_set()设为True
    e.clear() 将is_set()设为False
    e.wait() 判断is_set的bool值,如果bool为True 则非阻塞,bool值为False则阻塞
    e.is_set()标识
    from multiprocessing import Process,Event
    import time
    import random
    
    def tra(e):
        '''信号灯函数'''
        # e.set()
        # print('33[32m 绿灯亮! 33[0m')
        while 1:# 红绿灯得一直亮着,要么是红灯要么是绿灯
            if e.is_set():# True,代表绿灯亮,那么此时代表可以过车
                time.sleep(5)# 所以在这让灯等5秒钟,这段时间让车过
                print('33[31m 红灯亮! 33[0m')# 绿灯亮了5秒后应该提示到红灯亮
                e.clear()# 把is_set设置为False
            else:
                time.sleep(5)# 此时代表红灯亮了,此时应该红灯亮5秒,在此等5秒
                print('33[32m 绿灯亮! 33[0m')# 红的亮够5秒后,该绿灯亮了
                e.set()# 将is_set设置为True
    
    def Car(i,e):
        e.wait()# 车等在红绿灯,此时要看是红灯还是绿灯,如果is_set为True就是绿灯,此时可以过车
        print('第%s辆车过去了'%i)
    
    if __name__ == '__main__':
        e = Event()
        triff_light = Process(target=tra,args=(e,))# 信号灯的进程
        triff_light.start()
        for i in range(50):# 描述50辆车的进程
            if i % 3 == 0:
                time.sleep(2)
            car = Process(target=Car,args=(i+1,e,))
            car.start()

    十二.学习生产者消费者模型

      主要用于解耦(耦合度)

  • 相关阅读:
    不舍
    java 笔记
    Javascript 行为委托
    JavaScript 函数调用的 this词法
    Javascript 闭包
    Javascript 原型链
    理解css的BFC
    多模态检索之CCA算法
    MySQL 基础概念、基础配置、密码破解
    Python的进程和线程
  • 原文地址:https://www.cnblogs.com/ITdong-1/p/9506720.html
Copyright © 2011-2022 走看看