系统知识
计算机抽象组成:CPU + 存储器 + IO
资源:
1.计算资源:CPU
2.存储资源:内存、磁盘等
系统知识
cpu时间片
对于单核cpu同一时刻只能有一个任务运行
1.并发:交替执行(某时间段内的处理能力)
2.并行:同时执行
进程与进程之间的通信方式
管道
匿名管道(父子进程之间才能通信)
命名管道(不是父子进程也能通信)
信号
异步通信
发送信号
硬件 ctrl + c
信号量
共享内存
socket
消息队列
进程线程
■ 系统知识• 线程:线程是操作系统最小的调度单位,是一串指令的集合• 进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位
进程与线程
• 真正在cpu上运行的是线程• 线程共享内存空间;进程的内存是独立的• 一个线程只能属于一个进程,而一个进程可以有多个线程, 但至少有一个线程• 资源分配给进程,同一进程的所有线程共享该进程的所有资 源。进程的资源是独立的• 同一个进程的线程之间可以直接交流;两个进程想通信,必 须通过一个中间代理来实现
进程 VS 线程
进程 vs 线程
1.一个进程里面是可以有一个以上的线程,这些线程都是可以共享这个内存空间的
2.不同进程之间内存空间都是独立的
3.创建新的线程很简单,创建一个新的进程需要对其父进程进程一次克隆
4.一个线程可以控制和操作同一个进程里的其他线程,进程只能操作子进程
5.一个主线程改变,可能会影响 其他线程,改变父进程不会影响子进程
多任务操作系统工作模式
多进程模式
多线程模式
多进程 + 多线程模式
一般来说多线程的开销会比多进程少
进程状态模型
进程的三态模型
进程的五态模型
Linux五种状态:
运行、中断,不可中断、僵尸、停止状态
运行 ( 正在运行或在运行队列中等待 ) R
中断 ( 休眠中, 受阻, 在等待某个条件的形成或接受到信号 ) S
不可中断 ( 收到信号不唤醒和不可运行, 进程必须等待直到有中断发生 ) D
僵尸 ( 进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放 ) Z
停止 ( 进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行 ) T
使用top命令查看这五种状态
load average :就绪 + 运行状态 线程队列的一个情况来反映出cpu一段时间内的繁忙程度
例如:1核cpu load average = 1 表示已经处于满负荷的临界点了,load average > 1 就超负荷了。
2核cpu load average = 2 表示已经处于满负荷的临界点,load average >2就超负荷了。
load average: 0.03, 0.02, 0.05
三个数值,代表1分钟,5分钟,15分钟,表示该时间段内的平均负载
例如:15,5,3 表示最近的时间段负载增长过快
3,5,15表示最近的时间段负载降低
系统监控命令的数据来源是 /proc目录
/proc 目录在内存的,系统启动以后自动加载
Threading - Thread
threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。
■ Thread构造方法• 构造方法:Thread(group=None, target=None, name=None, args=(), kwargs={})• group: 线程组,目前还没有实现,库引用中提示必须是None;• target: 要执行的方法;• name: 线程名;• args/kwargs: 要传入方法的参数。
■ Thread实例方法• t.name:获取或设置线程的名称• t.getName()/setName(name): 获取/设置线程名。• t.is_alive()、t.isAlive():判断线程是否为激活状态。返回线程是否在运行。正在运行指启动后、终 止前。• t.ident :获取线程的标识符。线程标识符是一个非零整数,只有在调用了start()方法之后该属性才 有效,否则它只返回None• t.run() :线程被cpu调度后自动执行线程对象的run方法• t.start(): 线程准备就绪,等待CPU调度,start会自动调用t.run()
"""
@name : 01.threading模块
@author : wangshenghu
@projectname: tlbb
@Date : 2022/8/5
"""
import requests
import functools
import time
import threading
def runtime(func):
# 保留传递进来的函数的元数据,将它的元数据赋值给inner
@functools.wraps(func)
def inner(*args, **kwargs): # 让装饰器更加通用
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"函数执行花了{end -start}s")
return result
return inner
def get_content(url):
text = requests.get(url).content
time.sleep(0.5)
print("get content")
@runtime
def main():
t_list = []
for i in range(5):
# get_content("https://www.baidu.com")
# 创建线程
# target -->指定传入的方法的名字 , 要做什么
# args --》 指定方法需要传入的参数 元组类型
# 子线程只做target里面规定的事情
t = threading.Thread(target=get_content, args=("https://www.baidu.com",))
t_list.append(t)
t.start() # 启动线程 #--》自动执行run方法
for t in t_list:
# 阻塞当前环境上下文,知道t的线程执行完成
# 谁执行这个join代码,谁就是当前环境
t.join()
main()
执行结果:
E:\python\python3.9.1\python.exe E:/tlbb/2022-08-05-多进程-多线程-协程/01.threading模块.py
get contentget content
get content
get content
get content
函数执行花了0.8148140907287598s
Process finished with exit code 0
• t.join([timeout]): 阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout 可选参数)。• t.setDaemon(bool): 设置是后台线程(默认前台线程(False))。(在start之前设置)• 如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止• 如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程 也执行完成后,程序停止• t.isDaemon:判断是否为后台线程
Threading - Lock
在多线程中使用lock可以让多个线程在共享资源的时候遵循一定的规则。常见锁类型• Lock()/RLock:普通锁(互斥锁)解决资源争用,数据读取不一致等• Semaphore :信号量最多允许同时N个线程执行内容• Event: 事件锁根据状态位,决定是否通过事件• Condition: 条件锁
示例:互斥锁
没有添加互斥锁的时候,使用多线程可能会出现资源占用的情况
import threading
import time
num = 0
def sum_num(i):
global num
time.sleep(0.5)
num += i
print(num)
for i in range(5):
t = threading.Thread(target=sum_num, args=(i,))
t.start()
执行结果:
E:\python\python3.9.1\python.exe E:/tlbb/2022-08-05-多进程-多线程-协程/03.互斥锁.py
47
7
910
示例:添加互斥锁以后
"""
@name : 03.互斥锁
@author : wangshenghu
@projectname: tlbb
@Date : 2022/8/5
"""
# 互斥锁,
import threading
import time
num = 0
def sum_num(i):
# 获取锁,同一时间只能有一个线程在这里运行,解决资源占用问题
lock.acquire()
global num
time.sleep(0.5)
num += i
print(num)
# 释放锁
lock.release()
# 创建一个锁对象
lock = threading.Lock()
for i in range(5):
t = threading.Thread(target=sum_num, args=(i,))
t.start()
执行结果
E:\python\python3.9.1\python.exe E:/tlbb/2022-08-05-多进程-多线程-协程/03.互斥锁.py
0
1
3
6
10
还可以使用with语句来写互斥锁语句
with lock:
global num
time.sleep(0.5)
num += i
print(num)