并发编程知识点汇总

计算机输入和输出的过程就称为“IO”(“input”、“output”),比如 程序一旦执行,就由操作系统决定cpu和Io的优化算法,不能人为干预,比如 input、time.sleep()、读文件、写文件都是Io
比如读文件,就是从硬盘中读取到内存中,此时和CPU还没发生关系


操作系统的三种类型:(我们现在常用的操作系统是具有多种操作特征的操作系统,或者具备以下两种或以上)
多道批处理系统:
(多个程序执行,遇见IO的话CPU就切换任务)
分时系统:
(多个程序执行,按时间轮流执行,时间到的话CPU就切换任务)
实时系统:
(多个程序执行,一直等着响应,CPU不切换,一般用于军事、情报、银行等等)




硬盘➡️内存➡️CPU 硬盘读取到内存是机械爪在工作,CPU是从内存总读取数据然后

,所以以上两者工作的时候互不影响。


两个程序同时运行的时候,在内存中各自占领一块儿互不干涉的内存空间,而分配内存空间这件事儿是操作系统干的,
两个程序同时运行的时候:
从宏观上看是并行的(看着确实是两个程序在同时运行)
从微观上看是串行的(实际上还是轮流使用CPU)
 



所谓并发就是有多个进程 在同一时刻执行同一段代码

子进程中不能有input,因为主进程与子进程是两个单独的进程

多进程实现并发效果
开启多进程有两种方法
人为和内存打交道或者硬盘和内存打交道,不涉及到cpu计算的就是一个IO,
例如input或者从硬盘读取文件都是一个IO

操作系统的作用:
(1)隐藏硬件接口,提供良好的抽象接口
(2)管理、调度进程,将多个进程对硬件的竞争变的有序
运行中的程序就是进程
程序是一个没有生命的实体,只有运行它的时候才会成为一个活动的实体,我们称之为进程


并行:比如两个CPU执行两个程序,这时候进程之间就是并行
并发:比如一个CPU执行两个程序,这时候进程之间就是并发的,从宏观上看是同时执行的,从微观上看是轮流执行的
同步:比如去银行排队,一直等着就是同步,只能等着,其他什么也不能干
异步:比如去银行排队,拿着排队的号码,轮到我的时候银行柜台的人来喊我,而在等待的过程中我还能去干其他的事情
阻塞:time.sleep、input等就是阻塞
非阻塞:没有time.sleep、input等就是非阻塞
同步阻塞:效率最低,就像上面的去银行排队,等着的时候什么都不干
异步阻塞:就像上面银行排队拿了一张小纸条,等号的的时候可以干一些其他的事情
同步非阻塞:一边排队等号,一边打电话,还要在打电话与看看排队到自己没来回切换,效率是低下的
异步非阻塞:效率高,专心打电话,该自己办业务的时候有银行的人员通知自己办理
进程与子进程:比如运行pycharm是一个父进程,这时候在pycharm里面run文件,就是一个个的子进程,关系看下图


这个时候创建的子进程和下面的print不一定谁先执行,因为开启一个子进程,是就绪状态,等到时间片轮到这个进程的时候,这个进程才会启动

单进程:
多进程:


进程都有一个进程号,就是PID(P是Process,进程的意思)可以在任务管理器中查看
进程的生命周期如下图:


 
join():确保上面进程执行完毕再执行下面的代码,也就是使异步变为同步
多个进程之间的数据是完全隔离的,就算父进程与子进程之间的数据也是完全隔离的


进程三状态图







开启进程的第二种方式:




进程与进程之间的数据是完全隔离的


多进程中子进程常用属性和方法:
start():开始一个子进程
join():感知一个子进程的结束
terminate():结束一个进程
is_alive():检查一个进程是否结束
name:查看进程名
daemon:为True的时候,表示新的子进程是一个守护进程
守护进程:在进程start之前设置daemon为True
随着主进程的代码执行完毕而结束,这个子进程称之为守护进程,而不是随着主进程的结束而结束
     比如一个主进程有两个子进程,一个守护进程,一个平常的子进程,当主进程代码结束,而那个平常的子进程还没结束,这个时候守护进程也会结束,因为守护进程是随着
主进程的代码执行完毕而结束,而不是随着主进程的结束而结束


△:当terminate一个进程就是向操作系统发送一个关闭进程的请求 此时如果立即is_alive进程极有可能会显示为True,因为知识向操作系统发送关闭子进程的请求,操作系统可能不会立即执行,这中间还有一点儿缓冲时间
因为结束一个进程是向操作系统发送一个结束请求,系统不会立即反应过来,需要一个操作系统响应的过程

进程锁: from multiprocessing import Lock
lock = Lock()
需要加锁的代码前面:lock.acquire() #拿钥匙
需要加锁的代码前面:lock.release() #还钥匙
涉及到修改数据的代码操作都需要加锁


pycharm中开启子进程不能涉及到输入,因为开启子进程就相当于又开辟了一块儿新的空间,写聊天系统的时候server端也不会涉及到输入,因为最终聊天是客户端与客户端在聊天,而server端只是一个中间平台。



信号量: from multiprocessing import Semaphore
用途用法和进程锁一样,进程锁是控制一个进程工作,信号量是控制多个进程工作

事件:
from multiprocessing import Event
e = Event() #创建一个事件
print(e.is_set()) # 查看这个事件的阻塞状态,默认False
e.set() # 将这个事件的阻塞状态改为True
print(e.is_set())
e.wait() # 根据is_set()的值决定是否阻塞 True为不阻塞,False为阻塞
e.clear() # 将这个事件的阻塞状态改为False
print(e.is_set())



进程间的通信: IPC(inter-process-commmunication)



队列:先进先出


from multiprocessing import Queue
q = Queue(3)#创建队列,参数为可放入的数量
q.put(1)#放入数据
q.put(2)
q.put(3)
print(q.get())#取数据,如果为空就阻塞
print(q.full())#查看队列是否满了
print(q.get())#取查看队列是否有空位
try:
print(q.get_nowait())#取数据,如果为空不阻塞,所以可用捕捉异常,另行处理
except:
print("没值了")

生产者消费者模型,以队列为基础



from multiprocessing import Process, JoinableQueue
import time, random
def produce(name, food, q):
    for i in range(1, 11):
        time.sleep(random.random())
        print("{}生产了{}{}".format(name, food, i))
        q.put("{}{}".format(food, i))
    q.join()

def consume(name, q):
    while 1:
        time.sleep(random.random())
        print("{}消费了{}".format(name, q.get()))
        q.task_done()


if __name__ == '__main__':
    q = JoinableQueue()
    p1 = Process(target=produce, args=("小黑", "包子", q))
    p1.start()
    p2 = Process(target=produce, args=("小白", "馒头", q))
    p2.start()
    c1 = Process(target=consume, args=("alex", q))
    c1.daemon = True
    c1.start()
    c2 = Process(target=consume, args=("egon", q))
    c2.daemon = True
    c2.start()
    p1.join()
    p2.join()
View Code
 
 

 

 

转载于:https://www.cnblogs.com/QimiSun/p/10012399.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值