并发编程: 操作系统发展史,IO操作,阻塞与非阻塞:,进程,僵尸进程与孤儿进程(了解),守护进程

操作系统发展史

1.UDP协议 (了解)

UDP协议:称之为数据包协议。

特点:

1) 不需要建立链接。
2) 不需要知道对方是否收到。
3) 数据不安全
4) 传输速度快
5)能支持并发
6) 不会粘包
7) 无需先启动服务端再启动客户端

优点:

- 传输速度快
- 能支持并发
- 不会粘包

缺点

- 数据不安全, 容易丢失

应用场景:

早期的QQ聊天室。

2.TCP协议

- TCP协议(称为流式协议):

优点

数据安全

缺点:

传输速度慢
粘包

面试:

TCP与UDP的区别, 简述优缺点即可
​

3.并发编程

1) 操作系统发展史

1.1 穿孔卡片

- 读取数据速度特别慢
- CPU的利用率极低
- 单用户(一份代码)使用
​

1.2 批处理

- 读取数据速度特别慢
- CPU的利用率极低
- 联机(多份代码)使用
- 效率还是很低
​

1.3 脱机批处理(现代操作系统的设计原理)

- 读取数据速度提高
- CPU的利用率提高
​

2) 多道技术 (基于单核背景下产生的):

单道

- 单道: 一条道走到黑   ---->  串行
- 比如: a,b需要使用cpu,a先使用,b等待a使用完毕后,b才能使用cpu。
​
​

多道

比如: a,b需要使用cpu,a先使用,b等待a,直到a进入“IO或执行时间过长”
a会(切换 + 保存状态),然后b可以使用cpu,待b执行遇到 “IO或执行时间过长”
再将cpu执行权限交给a,直到两个程序结束。
​

空间上的复用

多个程序使用一个CPU。
​

时间上的复用

切换 + 保存状态
​
1) 当执行程序遇到IO时,操作系统会将CPU的执行权限剥夺。
优点:
- CPU的执行效率提高
​
2) 当执行程序执行时间过长时,操作系统会将CPU的执行权限剥夺。
缺点:
- 程序的执行效率低
​

并发与并行

并发:

在单核(一个cpu)情况下,当执行两个a,b程序时,a先执行,当a遇到IO时,b开始争抢cpu的执行权限,再让b执行,他们看起像同时运行。
​

并行:

在多核(多个cpu)的情况下,当执行两个a,b程序时,a与b同时执行。他们是真正意义上的同时运行。
​

面试题:

在单核情况下能否实现并行? 
不行
​

3) 进程

1.什么是进程?

进程是一个资源单位。
​

2.进程与程序:

- 程序: 一对代码文件。
- 进程: 执行代码的过程,称之为进程。
​

3 进程调度: (了解)

1) 先来先服务调度算法(了解)
- 比如程序 a,b,若a先来,则让a先服务,待a服务完毕后,b再服务。
- 缺点: 执行效率低。
​
2) 短作业优先调度算法(了解)
- 执行时间越短,则先先调度。
缺点:
导致执行时间长的程序,需要等待所有时间短的程序执行完毕后,才能执行。
​
​
注意:
3) 时间片轮转法
- 比如同时有10个程序需要执行,操作系统会给你10秒,然后时间片轮转法会将10秒分成10等分。
​
4) 多级反馈队列:
1级队列: 优先级最高,先执行次队列中程序。
2级队列: 优先级以此类推
3级队列:
​

4) 同步与异步

同步与异步指的是 “提交任务的方式”。
​

同步(串行)

两个a,b程序都要提交并执行,假如a先提交执行,b必须等a执行完毕后,才能提交任务。
​

异步(并发)

两个a,b程序都要提交并执行,假如a先提交并执行,b无需等a执行完毕,就可以直接提交任务。
​

4) 阻塞与非阻塞

阻塞(等待):

- 凡是遇到IO都会阻塞。
- IO:
    input()
    output()
    time.sleep(3)
    文件的读写
    数据的传输
​

非阻塞 (不等待) :

- 除了IO都是非阻塞 (比如: 从1+1开始计算到100万)
​

5) 进程的三种状态

就绪态:

同步与异步
​

运行态:

程序的执行时间过长 ----> 将程序返回给就绪态。
- 非阻塞
​

阻塞态:

- 遇到IO
​

面试题:

阻塞与同步是一样的吗?非阻塞与异步是一样的吗?
​
- 同步与异步: 提交任务的方式
​
- 阻塞与非阻塞: 进程的状态。
​
- 异步非阻塞: ----> cpu的利用率最大化!
​

6)创建进程的两种方式:

同步演示

import time
​
def func():
    print('start...')
    time.sleep(3)
    print('end...')
​
​
if __name__ == '__main__':
    # 任务1:
    func()
​
    # 任务2:
    print('程序结束')
​

进程的两种创建方式

方式一

from multiprocessing import Process
import time
​
​
# 方式1: 直接调用Process
def task(name):  # 任务  # name == 'jason_sb'
    print(f'start...{name}的子进程')
    time.sleep(3)
    print(f'end...{name}的子进程')
​
​
if __name__ == '__main__':
    # target=任务(函数地址) ---> 创建一个子进程
    # 异步提交了三个任务
    p_obj1 = Process(target=task, args=('jason_sb', ))
    p_obj1.start()  # 告诉操作系统,去创建一个子进程
    p_obj1.join()  # 告诉主进程,等待子进程结束后,再结束
​
    p_obj2 = Process(target=task, args=('sean_sb', ))
    p_obj2.start()  # 告诉操作系统,去创建一个子进程
    p_obj2.join()  # 告诉主进程,等待子进程结束后,再结束
​
    p_obj3 = Process(target=task, args=('大饼_sb', ))
    p_obj3.start()  # 告诉操作系统,去创建一个子进程
    p_obj3.join()  # 告诉主进程,等待子进程结束后,再结束
​
    print('正在执行当前主进程...')
​
    list1 = []
​
    for line in range(10):
        p_obj = Process(target=task, args=('jason_sb',))
        p_obj.start()
        list1.append(p_obj)
​
    for obj in list1:
        obj.join()
​
    print('主进程')
​

 

方式二

# 方式二:
from multiprocessing import Process
import time
​
​
class MyProcess(Process):
    def run(self):
        print(f'start...{self.name}的子进程')
        time.sleep(3)
        print(f'end...{self.name}的子进程')
​
​
if __name__ == '__main__':
    list1 = []
​
    for line in range(10):
        obj = MyProcess()
        obj.start()
        list1.append(obj)
​
    for obj in list1:
        obj.join()
​
    print('主进程...')
​

 

进程号回收的两种条件:

'''windows:    创建子进程,windows会将当前父进程代码重新加载执行一次。        linux/mac:    会将当前父进程代码重新拷贝一份,再去执行。'''

from multiprocessing import Process
import time
'''
创建进程方式一:
'''
# 1.定义一个任务
def task(name):
    print(f'{name}的任务开始执行')
    time.sleep(1)
    print(f'{name}的任务已经结束')
​
# 在linux/mac系统下不会报错
p = Process(target=task, args=('jason',))
​
if __name__ == '__main__':
    # target=执行函数的地址
    p = Process(target=task, args=('jason',))
    # 向操作系统提交创建进程的任务
    p.start()
    print('主进程')
    
方法二:
# 创建进程方式二:
# 1.自定义一个类,并继承Process
class MyProcess(Process):
​
    # 父类的方法
    def run(self):
        print('任务开始执行')
        time.sleep(1)
        print('任务已经结束')
​
​
if __name__ == '__main__':
    p = MyProcess()
    p.start()
    # p.start()
    print('主进程')
    
主进程
任务开始执行
任务已经结束

#### 1.join,可以回收子进程与主进程。

join方法: 用来告诉操作系统,让子进程结束后,父进程再结束。
from multiprocessing import Process
import time
​
def task(name, n):
    print(f'{name} start...')
    time.sleep(n)
    print(f'{name} over..')
​
if __name__ == '__main__':
    p1 = Process(target=task, args=('jason', 1))
    p2 = Process(target=task, args=('egon', 2))
    p3 = Process(target=task, args=('sean', 3))
    p1.start()
    p2.start()  # 告诉操作系统,开启子进程
    p3.start()  # 告诉操作系统,开启子进程
​
    p1.join()  # 告诉操作系统,等子进程结束后,父进程再结束。
    p2.join()
    p3.join()
​
    print('主进程')
    
jason start...
sean start...
egon start...
jason over..
egon over..
sean over..
主进程

#### 2.主进程正常结束,子进程与主进程也会被回收。

current_process().pid: 获取子进程号
os.getpid(): 获取主进程pid号
​
cmd中查看进程号: tasklist |findstr 进程号
​
进程号回收的两种条件:
    1.join,可以回收子进程与主进程。
    2.主进程正常结束,子进程与主进程也会被回收。
​
os.getppid()
'''
from multiprocessing import Process
from multiprocessing import current_process
import os  # 与操作系统交互
import time
​
​
def task(name):
    print(f'{name} start...', current_process().pid)
    time.sleep(1)
    print(f'{name} over..', current_process().pid)
​
​
if __name__ == '__main__':
    p = Process(target=task, args=('jason', ))
    p.start()  # 告诉操作系统,开启子进程
​
    # 判断子进程是否存活
    print(p.is_alive())
​
    # 直接告诉操作系统,终止 子进程
    p.terminate()
    time.sleep(0.1)
​
    # 判断子进程是否存活
    print(p.is_alive())
​
    p.join()  # 告诉操作系统,等子进程结束后,父进程再结束。
​
    print('主进程', os.getpid())
    print('主主进程', os.getppid())
    time.sleep(100)

僵尸进程与孤儿进程(了解):

僵尸进程: ​ 指的是子进程已经结束,但PID号还存在,未销毁. ​ 缺点: ​ 占用PID号,占用操作系统资源.

孤儿进程:
        指的是子进程还在执行,但父进程意外结束.
        操作系统优化机制:
            提供一个福利院,帮你回收没有父亲的子进程.

守护进程:

指的是主进程结束后,该主进程产生的所有子进程跟着结束,并回收.

•
from multiprocessing import Process
from multiprocessing import current_process
import time
​
def task(name):
​
    print(f'{name} start...', current_process().pid)
​
    time.sleep(5)
​
    print(f'{name} over..', current_process().pid)
​
    print(f'管家{name}')
​
if __name__ == '__main__':
    p1 = Process(target=task, args=('jason', ))
​
    # 添加守护进程参数
    p1.daemon = True  # True代表该进程是守护进程
    p1.start()
​
    print(f'egon 驾鹤西去...')
​
•
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值