• 并发编程


    一.操作系统

     1.计算机的硬件组成:

    主板:       固化(寄存器,是直接和cpu进行交互的一个硬件)
    CPU:      中央处理器:计算(数字计算和逻辑计算)和控制(控制所有硬件协调工作)
    存储 :      硬盘,内存
    输入设备:   键盘,鼠标,话筒
    输出设备:  显示器,音箱,打印机

    2.计算机的发展史:

    第一代计算机:电子管计算机,及其耗电,体积庞大,散热量特别高
    第二代计算机:晶体管计算机,
    第三代计算机:白色大头计算机,集成电路计算机,一个板子固化几十到上百个小硬件
    第四代计算机:大型集成电路计算机,一个板子可以达到固化十万个硬件
    第五代计算机:甚大型集成电路计算机

    3.计算机的操作系统

    定义:操作系统是一个软件,是一个能直接操纵硬件的一个软件。

    目标:无论什么时候,操作系统的目标总是:让用户用起来更加的轻松。高可用,低耦合

      dos系统       纯编程系统    单用户单任务?
      windows系统 单用户多任务(早期windows)
      unix系统    多用户多任务

    操作系统的作用:

       1,封装所有硬件接口,让各种用户使用电脑更加轻松
       2,是对计算机内所有资源进行合理的调度和分配

    4.语言的发展史:

    计算机识别的是二进制,
    机器语言,由1 和 0组成代码
    汇编语言,指令形式,  add n,m      move  n,m
    高级语言:面向过程语言(C),面向对象语言(C++,JAVA,python,.net,php)

    二.进程

    1.进程概念:是指正在进行的程序

       组成: 代码段,数据段,PCB(进程管理控制)

       进程的三大基本状态:

    就绪状态:已经获得运行需要的所有资源,除了CPU
    执行状态:已经获得了所有资源包括cpu,处于正在运行
    阻塞状态:因为各种原因,进程放弃了cpu,导致进程无法继续执行,此时进程处于内存中,继续等待获取cpu
    进程的一个特殊状态:
        挂起状态:是指因为种原因,进程放弃了cpu,导致进程无法继续执行,此时进程被踢出内存。

    2.六个名词:

        并行 : 两个进程在同一时间点发生
        并发 : 两个进程在同一时间间隔内运行
        同步 : 某一个任务的执行必须依赖于另一个任务的返回结果
        异步 : 某一个任务的执行,不需要依赖于另一个任务的返回,只需要告诉另一个任务一声
        阻塞 : 程序因为类似于IO等待、等待事件等导致无法继续执行。
        非阻塞:程序遇到类似于IO操作时,不再阻塞等待,如果没有及时的处理IO,就报错或者跳过等其他操作

    3.进程的两种开启方法:

    (1) p = Process(target=None,args(,))

    from multiprocessing import Process
    import time
    import os
    
    def func(i):
        time.sleep(1)
        print('这里是儿子进程,儿子自己的pid是%s,儿子的父进程的pid是%s'%(os.getpid(),os.getppid()))
    
    # os.getpid()获取的是当前进程自己的pid
    # os.getppid()获取的是当前进程的父进程的pid
    if __name__ == '__main__':
        p = Process(target=func,args=(1,))# 实例化一个进程对象
        p.start()# 开启一个子进程
        print('这里是父亲进程,父进程自己的pid是:%s,父亲的父亲的pid是%s'%(os.getpid(),os.getppid()))

    结果:

    这里是父亲进程,父进程自己的pid是:12220,父亲的父亲的pid是840
    这里是儿子进程,儿子自己的pid是12328,儿子的父进程的pid是12220

    (2) 自定义类,继承Process父类
    from multiprocessing import Process
    import time
    import os
    class MyProcess(Process):
        def __init__(self):
            super(MyProcess, self).__init__()
        def run(self):
            print('这是以继承类的方式开启的子进程')
    
    if __name__ == '__main__':
        p1 = MyProcess()
        p1.start()# 是指,解释器告诉操作系统,去帮我开启一个进程,   就绪状态
        p1.run()# 告诉操作系统,现在马上帮我执行这个子进程           执行
    结果:

    这是以继承类的方式开启的子进程
    这是以继承类的方式开启的子进程

     
    (3)进程的常用方法
    (1) start() 开启一个子进程
    (2) join() 异步变同步(就是让父进程停留在join这句话,等待子进程执行结束,父进程再继续执行)
    from multiprocessing import Process
    import time
    
    def func():
        for i in range(10):
            time.sleep(0.01)
            print('儿子在这里')
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()
        p.join()# 是让主进程等待子进程执行完。  现象:主进程执行到这句话,主进程阻塞住,等待子进程执行
        # time.sleep(1)
        for i in range(2):
            time.sleep(0.01)
            print('爸爸在这里')
    
    # 开启一个正常的子进程,父进程会等待子进程结束后,父进程也就是程序才结束
    # p.join()# 是让主进程等待子进程执行完。  现象:主进程执行到这句话,主进程阻塞住,等待子进程执行
    # 如何把父进程和子进程之间的关系变为同步或者异步?
    # 父进程执行join,就会变成同步,不执行join,父进程和子进程就是异步的关系
    # join必须放在start()后边
    结果:
    儿子在这里
    儿子在这里
    儿子在这里
    儿子在这里
    儿子在这里
    儿子在这里
    儿子在这里
    儿子在这里
    儿子在这里
    儿子在这里
    爸爸在这里
    爸爸在这里
      (3) is_alive() 判断进程是否活着
    (4) terminate() 杀死进程
    from multiprocessing import Process
    import time
    def func():
        time.sleep(1)
        print(123)
    if __name__ == '__main__':
        p = Process(target=func,)
        p.start()
        p.terminate()# 杀死p进程,让解释器告诉操作系统,请杀掉p进程。
        print('子进程是否还活着?', p.is_alive())
        time.sleep(0.002)
        print('子进程是否还活着?', p.is_alive())
        # 返回一个bool值,如果返回True,代表进程还活着,如果返回False,代表子进程死了
    # p.is_alive() 判断p进程是否还活着
    # p.terminate() 杀死p进程
    
    结果:
    子进程是否还活着? True
    子进程是否还活着? False

    (4) 进程的常用属性

    from multiprocessing import Process
    import time
    import os
    
    def func():
        print('这里是儿子,儿子的pid是%s'%(os.getpid()))
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()
        p.name = 'alex'
        print('儿子的名字是%s'%p.name)
        print('儿子的pid是%s'%p.pid)
        print('儿子是不是守护进程?',p.daemon)
    结果:
    儿子的名字是alex
    儿子的pid是14260
    儿子是不是守护进程? False
    这里是儿子,儿子的pid是14260

    (5)守护进程

    守护进程:跟随着父进程的代码执行结束,守护进程就结束

    特点:

    随着父进程的代码执行完毕才结束
    守护进程不能创建子进程
    守护进程必须要在start之前设置
    from multiprocessing import Process
    import time
    
    def func():
        time.sleep(100)
        print('这里是儿子哦')
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.daemon = True # 将p进程设置为守护进程,必须要在start之前设置
        p.start()
        time.sleep(1)
        print('这是爸爸')

    三.进程间通信

    1.学习锁机制:

    l = Lock()
            一把锁配一把钥匙
            拿钥匙,锁门  l.acquire()
            还钥匙,开门  l.release()
    #模拟12306抢票
    from multiprocessing import Process,Lock
    import time
    
    def check(i):
        with open('余票') as f:
            con = f.read()
        print('第%s个人查到余票还剩%s张'%(i,con))
    
    def buy_ticket(i,l):
        l.acquire()# 拿钥匙,锁门
        with open('余票') as f:
            con = int(f.read())
            time.sleep(0.1)
        if con > 0:
            print('33[31m 第%s个人买到票了33[0m'%i)
            con -= 1
        else:
            print('33[32m 第%s个人没有买到票33[0m'%i)
        time.sleep(0.1)# 是指 买完票后,把余票数量重写写入数据库的时间延迟
        with open('余票','w') as f:
            f.write(str(con))
        l.release()# 还钥匙,开门
    
    if __name__ == '__main__':
        l = Lock()
        for i in range(10):
            p_ch = Process(target=check,args=(i+1,))
            p_ch.start()
        for i in range(10):
            p_buy = Process(target=buy_ticket,args=(i+1,l))
            p_buy.start()
    结果:
    第3个人查到余票还剩3张
    第4个人查到余票还剩3张
    第2个人查到余票还剩3张
    第1个人查到余票还剩3张
    第5个人查到余票还剩3张
    第7个人查到余票还剩3张
    第8个人查到余票还剩3张
    第6个人查到余票还剩3张
    第9个人查到余票还剩3张
    第10个人查到余票还剩3张
     第3个人买到票了
     第2个人买到票了
     第1个人买到票了
     第4个人没有买到票
     第5个人没有买到票
     第7个人没有买到票
     第10个人没有买到票
     第6个人没有买到票
     第9个人没有买到票
     第8个人没有买到票

    锁机制:

    from multiprocessing import Lock
    
    l = Lock()
    
    l.acquire()# 拿走钥匙,锁门,不让其他人进屋
    
    l.release()# 释放锁。  还钥匙,开门,允许其他人进屋
    锁机制

    存钱问题:

    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)
    存钱问题

    2.学习信号机制

    sem = Semaphore(n)
    n : 是指初始化一把锁配几把钥匙,一个int型
    拿钥匙,锁门  l.acquire()
    还钥匙,开门  l.release()
    信号量机制比锁机制多了一个计数器,这个计数器是用来记录当前剩余几把钥匙的。
    当计数器为0时,表示没有钥匙了,此时acquire()处于阻塞。
    对于计数器来说,每acquire一次,计数器内部就减1,release一次,计数器就加1
    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()
    发廊
    from multiprocessing import Semaphore,Lock
    
    l = Lock()
    l.acquire()
    print(123)
    l.release()
    l.acquire()
    print(456)
    # l.release()
    l.acquire()
    print(678)
    举个例子

    3.学习事件机制

    e = Event()
            # e.set()    #将is_set()设为True
            # e.clear()  # 将is_set()设为False
            # e.wait()   #判断is_set的bool值,如果bool为True,则非阻塞,bool值为False,则阻塞
            # e.is_set() # 标识
            # 事件是通过is_set()的bool值,去标识e.wait() 的阻塞状态
            # 当is_set()的bool值为False时,e.wait()是阻塞状态
            # 当is_set()的bool值为True时,e.wait()是非阻塞状态
            # 当使用set()时,是把is_set的bool变为True
            # 当使用clear()时,是把is_set的bool变为False
    事件机制
    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()
    信号灯模拟
       


  • 相关阅读:
    基本类型数组与包装类型数组相互转换
    (转载)JVM中的内存模型与垃圾回收
    Python之threading多线程
    Python之基于socket和select模块实现IO多路复用
    Python之利用socketserver实现并发
    Python的网络编程socket模块
    Python设计模式之一(单例模式)
    Python异常处理
    Python面向对象之常用的特殊方法(5)
    Python面向对象之私有方法(4)
  • 原文地址:https://www.cnblogs.com/shuai1993/p/9512638.html
Copyright © 2020-2023  润新知