zoukankan      html  css  js  c++  java
  • 进程 多进程 同步异步 阻塞 非阻塞

    1.操作系统背景知识

    #一 操作系统的作用:
        1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口
        2:管理、调度进程,并且将多个进程对硬件的竞争变得有序
    
    #二 多道技术:
        1.产生背景:针对单核,实现并发
        ps:
        现在的主机一般是多核,那么每个核都会利用多道技术
        有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个
        cpu中的任意一个,具体由操作系统调度算法决定。
        
        2.空间上的复用:如内存中同时有多道程序
        3.时间上的复用:复用一个cpu的时间片
           强调:遇到io切,占用cpu时间过长也切,核心在于切之前将进程的状态保存下来,这样
                才能保证下次切换回来时,能基于上次切走的位置继续运行

    2.进程

    顾名思义,进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。
    
    进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展开的。
    
    所以想要真正了解进程,必须事先了解操作系统
    
    PS:即使可以利用的cpu只有一个(早期的计算机确实如此),也能保证支持(伪)并发的能力。将一个单独的cpu变成多个虚拟的cpu(多道技术:时间多路复用和空间多路复用+硬件上支持隔离),没有进程的抽象,现代计算机将不复存在。
    进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
    
    狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。
    广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
    
    第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
    第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。[3] 
    进程是操作系统中最基本、重要的概念。是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。
    
    从理论角度看,是对正在运行的程序过程的抽象;
    从实现角度看,是一种数据结构,目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序。
    
    
    动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
    并发性:任何进程都可以同其他进程一起并发执行
    独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
    异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
    结构特征:进程由程序、数据和进程控制块三部分组成。
    多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。
    
    程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
    而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
    程序可以作为一种软件资料长期存在,而进程是有一定生命期的。
    程序是永久的,进程是暂时的。
    
    注意:同一个程序执行两次,就会在操作系统中出现两个进程,所以我们可以同时运行一个软件,分别做不同的事情也不会混乱。
    View Code

     3.多进程

    import os
    import time
    from multiprocessing import Process
    def func(args,args2):
        print(args,args2)
        time.sleep(3)
        print('子进程 :', os.getpid())
        print('子进程的父进程 :', os.getppid())
        print(12345)
    
    if __name__ == '__main__':
        p = Process(target=func,args=('参数','参数2'))   # 注册
        # p是一个进程对象,还没有启动进程
        p.start()       # 开启了一个子进程
        print('*'*10)
        print('父进程 :',os.getpid()) # 查看当前进程的进程号
        print('父进程的父进程 :',os.getppid()) # 查看当前进程的父进程
    
    # 进程的生命周期
        # 主进程
        # 子进程
        # 开启了子进程的主进程 :
            # 主进程自己的代码如果长,等待自己的代码执行结束,
            # 子进程的执行时间长,主进程会在主进程代码执行完毕之后等待子进程执行完毕之后 主进程才结束
    View Code
    # join()
    import time
    from multiprocessing import Process
    
    def func(arg1,arg2):
        print('*'*arg1)
        time.sleep(5)
        print('*'*arg2)
    
    if __name__ == '__main__':
        p = Process(target=func,args=(10,20))
        p.start()
        print('hahahaha')
        p.join()     # 是感知一个子进程的结束,将异步的程序改为同步
        print('====== : 运行完了')
    多进程的方法join
    import os
    import time
    from multiprocessing import Process
    
    def func(filename,content):
        with open(filename,'w') as f:
            f.write(content*10*'*')
    
    if __name__ == '__main__':
        p_lst = []
        for i in range(10):
            p = Process(target=func,args=('info%s'%i,0))
            p_lst.append(p)
            p.start()
        for p in p_lst:p.join()   # 之前的所有进程必须在这里都执行完才能执行下面的代码
        print([i for i in os.walk(r'E:python10day37')])
    
    # 同步 0.1 * 500  = 50
    # 异步 500 0.1    = 0.1
    # 多进程写文件
    # 首先往文件夹中写文件
    # 向用户展示写入文件之后文件夹中所有的文件名
    开启多个子进程
    class MyProcess(Process):
        def __init__(self,arg1,arg2):
            super().__init__()
            self.arg1 = arg1
            self.arg2 = arg2
    
        def run(self):
            print(self.pid)
            print(self.name)
            print(self.arg1)
            print(self.arg2)
    
    if __name__ == '__main__':
        p1 = MyProcess(1,2)
        p1.start()
        p2 = MyProcess(3,4)
        p2.start()
    
    # 自定义类 继承Process类
    # 必须实现一个run方法,run方法中是在子进程中执行的代码
    开启多进程的第二种方法
    import os
    from multiprocessing import Process
    
    
    def func():
        global n
        n = 0
        print('pid: %s'%os.getpid(),n)
    
    if __name__ == '__main__':
    
        n = 100
        p = Process(target = func)
        p.start()
        p.join()
        print(os.getpid(), n)
    多进程之间的数据隔离
    server端
    
    import socket
    from multiprocessing import Process
    def serve(conn):
        ret = ('你好').encode('utf-8')
        conn.send(ret)
        msg = conn.recv(1024).decode('utf-8')
        print(msg)
        conn.close()
    
    if __name__ =='__main__':
        sk = socket.socket()
        sk.bind(('127.0.0.1',8080))
        sk.listen()
        while True:
            conn,addr = sk.accept()
            p = Process(target = serve,args = (conn,))
            p.start()
    
    
        sk.close()
    
    
    client端
    
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    # sk.send('你好'.encode('utf-8'))
    msg = sk.recv(1024).decode('utf-8')
    print(msg)
    msg2 = input('>>>>').encode('utf-8')
    sk.send(msg2)
    sk.close()
    使用多进程实现socket服务端的并发效果
    # 子进程 -- > 守护进程
    import time
    from multiprocessing import Process
    
    def func():
        while True:
            time.sleep(0.2)
            print('我还活着')
    
    def func2():
        print('in func2 start')
        time.sleep(8)
        print('in func2 finished')
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.daemon = True   # 设置子进程为守护进程
        p.start()
        p2 = Process(target=func2)
        p2.start()
        p2.terminate()     # 结束一个子进程
        time.sleep(1)
        print(p2.is_alive())  # 检验一个进程是否还活着
        print(p2.name)
        # i = 0
        # while i<5:
        #     print('我是socket server')
        #     time.sleep(1)
        #     i+=1
    
    # 守护进程 会 随着 主进程的代码执行完毕 而 结束
    # 在主进程内结束一个子进程 p.terminate()
        #  结束一个进程不是在执行方法之后立即生效,需要一个操作系统响应的过程
    # 检验一个进程是否活着的状态 p.is_alive()
    # p.name p.pid 这个进程的名字和进程号
    守护进程
    #
    
    # 火车票
    import json
    import time
    from multiprocessing import Process
    from multiprocessing import Lock
    
    # def show(i):
    #     with open('ticket') as f:
    #         dic = json.load(f)
    #     print('余票: %s'%dic['ticket'])
    
    def buy_ticket(i,lock):
        lock.acquire() #拿钥匙进门
        with open('ticket') as f:
            dic = json.load(f)
            time.sleep(0.1)
        if dic['ticket'] > 0 :
            dic['ticket'] -= 1
            print('33[32m%s买到票了33[0m'%i)
        else:
            print('33[31m%s没买到票33[0m'%i)
        time.sleep(0.1)
        with open('ticket','w') as f:
            json.dump(dic,f)
        lock.release()      # 还钥匙
    
    if __name__ == '__main__':
        # for i in range(10):
        #     p = Process(target=show,args=(i,))
        #     p.start()
        lock = Lock()
        for i in range(10):
            p = Process(target=buy_ticket, args=(i,lock))
            p.start()
    进程锁
    from multiprocessing import Process
    from multiprocessing import Semaphore
    import random
    import time
    def ktv(i,sem):
        sem.acquire()
        print('%s走进ktv'%i)
        time.sleep(random.randint(6,10))
        print('%s走出ktv'%i)
        sem.release()
    
    if __name__ == '__main__':
        sem = Semaphore(4)
        for i in range(20):
            p = Process(target = ktv,args = (i,sem))
            p.start()
    信号量--示例1
    # 通过一个信号 来控制 多个进程 同时 执行或者阻塞
    # 事件
    # from multiprocessing import Event
    # 一个信号可以使所有的进程都进入阻塞状态
    # 也可以控制所有的进程解除阻塞
    # 一个事件被创建之后,默认是阻塞状态
    # e = Event()  # 创建了一个事件
    # print(e.is_set())   # 查看一个事件的状态,默认被设置成阻塞
    # e.set()      # 将这个事件的状态改为True
    # print(e.is_set())
    # e.wait()     # 是依据e.is_set()的值来决定是否阻塞的
    # print(123456)
    # e.clear()    # 将这个事件的状态改为False
    # print(e.is_set())
    # e.wait()     # 等待 事件的信号被变成True
    # print('*'*10)
    
    
    # set 和 clear
        #  分别用来修改一个事件的状态 True或者False
    # is_set 用来查看一个事件的状态
    # wait 是依据事件的状态来决定自己是否在wait处阻塞
        #  False阻塞 True不阻塞
    
    
    # 红绿灯事件
    import time
    import random
    from multiprocessing import Event,Process
    def cars(e,i):
        if not e.is_set():
            print('car%i在等待'%i)
            e.wait()    # 阻塞 直到得到一个 事件状态变成 True 的信号
        print('33[0;32;40mcar%i通过33[0m' % i)
    
    def light(e):
        while True:
            if e.is_set():
                e.clear()
                print('33[31m红灯亮了33[0m')
            else:
                e.set()
                print('33[32m绿灯亮了33[0m')
            time.sleep(2)
    
    if __name__ == '__main__':
        e = Event()
        traffic = Process(target=light,args=(e,))
        traffic.start()
        for i in range(20):
            car = Process(target=cars, args=(e,i))
            car.start()
            time.sleep(random.random())
    事件
  • 相关阅读:
    Oracle Words Spelling Error
    原创 分布式锁与应用场景
    原创 分布式事务简单实现思路
    原创 使用redis位图实现布隆过滤器
    原创 redis实现接口限流
    原创 jwt-security简单实现
    原创 抢购秒杀之redis高性能实现
    原创 springcloud feign优化配置
    原创 派单、抢单业务简单实现
    原创 微信公众号推送图片实现
  • 原文地址:https://www.cnblogs.com/shangchunhong/p/9272621.html
Copyright © 2011-2022 走看看