• 并发编程(初学)


    并发编程(初学)

    一、操作系统的发展史

    1、第一代计算机:真空管和穿孔卡片

    • 特点:没有操作系统的概念,所有的程序设计都是直接操控硬件
    • 优点:程序员在申请的时间段内独享整个资源,可以即时地调试自己的程序
    • 缺点:浪费计算机资源,一个时间段内只有一个人用

    2、第二代计算机:晶体管和批处理系统

    • 特点:有了操作系统的概念,有了程序设计语言:FORTRAN语言或汇编语言,写到纸上,然后穿孔打成卡片,再讲卡片盒带到输入室,交给操作员,然后喝着咖啡等待输出接口

    • 优点:批处理,节省了机时和资源

    • 缺点:1.整个流程需要人参与控制,将磁带搬来搬去

        	 2.计算的过程仍然是顺序计算-》串行
      

      ​ 3.程序员原来独享一段时间的计算机,现在必须被统一规划到一批作业中,等待结果和重新调试的过程都需要 等同批次的其他程序都运作完才可以(这极大的影响了程序的开发效率,无法及时调试程序)

    3、第三代计算机:集成电路复用和多道程序设计

    • 多道技术:

      ​ 1、产生背景:针对单核,实现并发

      (现在的主机一般是多核,那么每个核都会利用多道技术。有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个cpu中的任意一个,具体由操作系统调度算法决定。

      ​ 2、空间复用:共用一个内存条,每一个进程都有自己独立的内存空间,互不干扰,物理级别的隔离

      ​ 3、时间复用:共用一个cpu,IO的时候占用时间过长

    4、第四代计算机:个人计算机

    二、必备的理论基础

    1、操作系统的作用:

    ​ 1、隐藏丑陋复杂的硬件接口,提供良好的抽象接口

    ​ 2、管理、调度进程,并且将多个进程对硬件的竞争变得有序

    2、cpu切换:

    ​ 遇到io切换,占用cpu时间过长也切换,核心在于切之前将进程的状态保存下来,这样才能保证下次切换回来时,能基于上次切走的位置继续运行

    三、进程

    1. 进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
    2. 进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。

    进程是操作系统中最基本、重要的概念。是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。

    四、创建并开启子进程的两种方式

    4.1 方式一

    #单个进程
    from multiprocessing import Process
    import time
    
    def Text():
        print('我是一个子进程')
        print('我的进程开始了')
        time.sleep(2)
        print('我的进程结束了')
    
    
    if __name__ == '__main__':  #windows下必须要写这一句,不然会报错
        p = Process(target = Text)   #实例化产生一个对象
        p.start()   # 告诉操作系统我要开子进程,告诉完了这行代码就算执行完了,接着往下走,具体操作系统什么时候开子,开多长时间跟你没关系
        time.sleep(5)
        print('我是主进程,我要结束了')
    #多个进程
    
    #多个进程
    from multiprocessing import Process
    import time
    
    def Text(x):
        print(f'我是子进程{x}')
        print(f'{x}的进程开始了')
        time.sleep(2)
        print(f'{x}的进程结束了')
    
    
    if __name__ == '__main__':  #windows下必须要写这一句,不然会报错
        p1 = Process(target = Text,args=('yjy',))   #实例化产生一个对象  子进程1
        p2 = Process(target = Text,args=('ypp',))   #实例化产生一个对象  子进程2
        p1.start()   # 告诉操作系统我要开子进程,告诉完了这行代码就算执行完了,接着往下走,具体操作系统什么时候开子,开多长时间跟你没关系
        p2.start()   # 告诉操作系统我要开子进程,告诉完了这行代码就算执行完了,接着往下走,具体操作系统什么时候开子,开多长时间跟你没关系
        time.sleep(5)
        print('我是主进程,我要结束了')
    

    4.2 方式二

    from  multiprocessing import Process
    import time
    
    class Text(Process):  #定义一个类,让他继承Process
        def __init__(self,name):    #重写__init__
            super().__init__()   #继承父类的__init__方法
            self.name = name
    
        def run(self):  #定义一个函数
            print(f'子进程的姓名为{self.name},子进程开始')
            time.sleep(2)
            print(f'{self.name}进程结束')
    
    
    if __name__ == '__main__':
        p = Text('yjy')
        p.start()  #通知操作系统子进程开始
        print('主进程结束')
    

    五、验证进程的内存空间隔离

    from multiprocessing import Process
    import time
    
    x = 0  #定义一个变量x
    def Check():
        global x
        x = 100
        print(f'子进程的x:{x}')
    
    
    if __name__ == '__main__':
        p = Process(target=Check)
        p.start()
        print(f'父进程的x:{x}')
       
    

    父进程的x:0
    子进程的x:100

    父进程的x和子进程的x不是一个值,说明他们两个进程互不影响!

    六、僵尸进程和孤儿进程

    僵尸进程(有害):当子进程结束的时候,不会将所有内容都释放掉,他会留下自己的pid(类似身份证号码)供父进程来查看,此所谓进程死了没死干净,这就是僵尸进程,他会等待父进程最后把他处理掉

    孤儿进程(无害):一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

  • 相关阅读:
    SQL常见问题及解决备忘
    工厂方法模式-Factory Method
    访问者模式-Visitor
    解释器模式-Interpreter
    享元模式-Flyweight
    系统的重要文件/etc/inittab被删除了--急救办法!
    Database基础(二):MySQL索引创建与删除、 MySQL存储引擎的配置
    轻松解决U盘拷贝文件时提示文件过大问题
    Cisco基础(六):配置目前网络环境、项目阶段练习
    Cisco基础(五):配置静态NAT、配置端口映射、配置动态NAT、PAT配置、办公区Internet的访问
  • 原文地址:https://www.cnblogs.com/zhuangyl23/p/11509114.html
Copyright © 2020-2023  润新知