zoukankan      html  css  js  c++  java
  • 掌握并发编程1

    一、操作系统介绍

      1.1、什么是操作系统

        操作系统是一个协调、管理和控制计算机硬件资源和软件资源的控制程序。

        1、操作系统的内核

          运行于内核态,管理硬件资源

        2、系统调用

          运行于用户态,为程序员写的应用程序提供系统调用接口。

      1.2、操作系统的功能

        1、隐藏了复杂的硬件调用接口,为程序员提供调用硬件资源的更好、更简单、更清晰的模型(系统调用接口)

          例如:用操作文件的方式,代替关于磁盘读写的操作

        2、将应用程序对硬件资源的请求变得有序化

      1.3、操作系统与普通软件的区别

        1、操作系统由硬件保护,不能被用户修改

        2、操作系统是一个大型、复杂、长寿的软件

          大型:Windows和Linux仅内核源码就有500多万行,用户程序,如GUI、库、以及基本应用软件(如Windows explorer 等)很容易再扩充10到20倍。

          长寿:操作系统一旦完成,不会轻易替换,而是在原有基础上改进 

      1.4、操作系统发展史

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

          特点:

            1、没有操作系统概念

            2、所有的程序设计都是直接操控硬件

          优点:
            1、程序员在申请的时间段内独享整个资源,可以即时的调试自己的程序(随时处理bug)

          缺点:

            1、浪费计算机资源,一个时间段内只有一个人使用

            2、同一时刻只有一个程序在内存中运行,多个程序的执行是串行的

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

          特点:

            1、设计人员、生产人员、操作人员、程序人员和维护人员直接有了明确的分工,计算机被所在专用空调房间中,由专业操作人员运行。

            2、有了操作系统的概念

            3、有了程序设计语言。将FORTRAN语言或汇编语言写在纸上,然后穿孔打成卡片,将多个人的卡片盒拿到输入室,由操作人员操作计算机统一运算,结果输出到磁带上。

          优点:
            1、批处理,节省了机时

          缺点:

            1、整个流程需要人为参与控制,不停运输磁带
            2、计算过程仍然是串行

            3、执行的程序被统一规划到一批作业中,无法及时调试程序,影响了开发效率。

        1.4.3、第三代计算机:集成电路芯片和多道程序设计

            多道技术:用多路复用的方法控制多个程序有序的竞争或共享一个资源(如CPU)。

            多路复用:

              1、空间上的复用:将内存分为几个部分,每个部分放入一个程序,这样同一时间内存中就有了多道程序
              2、时间上的复用:当一个程序在等待 I/O 时,另一个程序可以使用CPU,让CPU的利用率接近百分百。一个程序长时间占用CPU也会被操作系统自动切换。

            分时操作系统:多个联机终端+多道技术

        1.4.4、个人计算机

              

    二、进程理论

      2.1、什么是进程
        正在进行的一个过程或一个任务,由CPU执行。

      2.2、进程与程序的区别

        程序是一堆代码,进程是程序的运行过程

      2.3、并发与并行
        1、并发:

          伪并行,由单个CPU+多道技术即可实现

        2、并行:
          同时运行,需要具备多个CPU

      2.4、进程的层次结构:
        1、Linux:所有进程以 init 为根,组成树形结构,父子进程公用一个进程组。

        2、Windows:没有进程层次概念,所有进程地位相同。

      2.5、进程的状态:

        阻塞态、运行态、就绪态

        进程在逻辑上无法运行的两种原因:
          1、自身原因,遇到 I/O 阻塞,让出CPU执行其他程序

          2、操作系统原因,一个进程占用时间过多,或者优先级的原因,让出CPU。

    三、开启进程的两种方式

      3.1、multiprocessing 模块

        功能:开启子进程,并在子进程中执行定制的任务。提供了Process、Queue、Pipe、Lock等组件

      3,2、Process 类

        由该类实例化的到的对象,可用来开启一个子进程

        3.2.1、参数

          group        参数未使用,始终为None

          target        表示调用对象,即子进程要执行的任务

          args          表示调用对象的位置参数,写作元组形式。

          kargs        表示调用对象的字典.

          name        表示子进程名字

        3.2.2、方法

          p.start()    启动进程,调用该子进程中的 p.run()

          p.run()        进程启动运行的方法,正是它去调用 target 指定的函数。

          p.terminate()    强制终止进程 p,不会进行任何清理操作,如果 p 创建了子进程,该进程就成了僵尸进程。如果p保留了锁,也不会被释放,而成为死锁。

          p.is_alive()    判断 p 是否仍然运行

          p.join([timeout])  主线程等待 p 终止,timeout 是可选的超时时间

        3.2.3、属性

          p.deamon   默认值为 False,如果设为 True,代表 p 为后台运行的守护进程,当 p 的父进程终止时,p 也随之终止。设定为True后,p 还不能创建自己

                  的新进程,必须在 p.start() 之前设置。

          p.name    进程的名称

          p.pid      进程的端口地址

      3.3、Process 的使用

        注意:在 Windows 中 Process() 必须放到 if __name__ == '__main__': 下

        1、

    import time
    import random
    from multiprocessing import Process
    
    
    def study(name):
        print('%s study' % name)
        time.sleep(random.randrange(1, 5))
        print('%s study end' % name)
    
    
    if __name__ == '__main__':
        p1 = Process(target=study, args=('a',))
        p2 = Process(target=study, args=('b',))
        p3 = Process(target=study, args=('c',))
    
        p1.start()
        p2.start()
        p3.start()
        print('')
        

        2、

    import time
    import random
    from multiprocessing import Process
    
    
    class Study(Process):
        def __init__(self, name):
            super().__init__()
            self.name = name
    
        def run(self):
            print('%s study' % self.name)
            time.sleep(random.randrange(1, 5))
            print('%s study end' % self.name)
    
    
    if __name__ == '__main__':
        p1 = Study('a')
        p2 = Study('b')
        p3 = Study('c')
        
        p1.start()
        p2.start()
        p3.start()   
        print('')
        

    四、join方法

      4.1、process 对象的 join 方法

        作用:如果主进程的任务在执行到某一阶段时,需要等待子进程执行完毕后才能继续执行,就需要有一种机制能够让主进程检测子进程是否运行完毕,

           在子进程执行完毕后才继续执行,否则一直在原地阻塞。

    from multiprocessing import Process
    import time
    import random
    import os
    
    
    def task():
        print('%s is studying' % os.getpid())
        time.sleep(random.randrange(1, 3))
        print('%s is sleeping' % os.getpid())
    
    if __name__ == '__main__':
        p = Process(target=task)
        p.start()
        p.join()
        print('')

    五、守护进程

      5.1、特点:

        1、守护进程会在主进程代码结束后终止
        2、守护进程内无法再开启子进程,否则抛出异常

      5.2、

    from multiprocessing import Process
    import time
    import random
    
    def task(name): print('%s is study' % name) time.sleep(random.randrange(1, 3)) print('%s is sleeping' % name) if __name__ == '__main__': p = Process(target=task, args=('a',)) p.daemon = True p.start() print('')

      

     六、互斥锁

      6.1、进程之间数据不共享,但是共享同一套文件系统,也由此带来了竞争,导致输出混乱。

        锁必须在主进程中产生,交给子进程使用。

        互斥锁特点:能将任务中某一段代码串行。

        1、并发运行,竞争同一终端导致打印错乱

    from multiprocessing import Process
    import os, time
    
    
    def work():
        print('%s is running' %os.getpid())
        time.sleep(2)
        print('%s is done' %os.getpid())
    
    
    if __name__ == '__main__':
        for i in range(3):
            p = Process(target=work)
            p.start()

        2、加锁后变成串行,牺牲了运行效率,但避免了竞争

    def work(mutex):
        mutex.acquire()
        print('%s is running' %os.getpid())
        time.sleep(2)
        print('%s is done' %os.getpid())
        mutex.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()
        for i in range(3):
            p = Process(target=work, args=(mutex,))
            p.start()

       6.2、模拟抢票练习

        1、在执行文件目录下创建名为 'data.txt' 的文件,用 json 的字典格式写入 {"ticket": 1}

        2、并发运行,效率高,但竞争写同一文件,数据写入错乱,一张票10个人都抢到

    from multiprocessing import Process
    import time
    import json
    
    
    #查票
    def search(i):
        with open('data.txt', 'r', encoding='utf-8') as f:
            data = f.read()
        ticket_num = json.loads(data)
        print('查询余票为:%s' % ticket_num.get('ticket'))
    #买票
    def buy(i):
        with open('data.txt', 'r', encoding='utf-8') as f:
            data = f.read()
        ticket_num = json.loads(data)
        time.sleep(3)
        if ticket_num.get('ticket') > 0:
            ticket_num['ticket'] -= 1
            with open('data', 'w', encoding='utf-8') as f:
                json.dump(ticket_num, f)
                f.flush()
            print('%s用户抢票成功' % i)
        else:
            print('没票了')
    
    def run(i):
        search(i)
        buy(i)
    
    if __name__ == '__main__':
        for i in range(10):
            p = Process(target=run, args=(i,))
            p.start()

        3、加锁处理,购票行为由并发变为串行,牺牲运行效率,保证了数据安全。

    from multiprocessing import Process, Lock
    import json
    import time
    
    
    def check():
        with open('data.txt', 'r', encoding='utf-8') as f:
            dict = json.load(f)
            ticket_num = dict['ticket']
            print('还剩%s张票' % ticket_num)
    
    def buy(i):
        with open('data.txt', 'r', encoding='utf-8') as f:
            dict = json.load(f)
            ticket_num = dict['ticket']
            time.sleep(1)
        if ticket_num > 0:
            dict['ticket'] -= 1
            with open ('data.txt', 'w', encoding='utf-8') as f:
                json.dump(dict, f)
                f.flush()
            print('用户%s抢票成功' % i)
        else:
            print('余票不足')
    
    def run(i, mutex):
        check()
        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()


        

      

  • 相关阅读:
    仿造email后缀自动添加功能(1)
    仿造email后缀搜索功能(2)
    取出input内的空格
    小知识点
    关于闭包
    js清除浏览器缓存的几种方法
    动态生成模板(模板生成器)
    安卓端调用h5界面js方法和ios端调用h5界面js方法
    linux 命令
    如何做个好员工
  • 原文地址:https://www.cnblogs.com/binyuanxiang/p/11343404.html
Copyright © 2011-2022 走看看