引入进程的目的是为了是多道程序并发执行,从而提高资源利用率和系统吞吐量
进程实体由程序段、数据和PCB(进程控制块)三部分构成,也称为进程映像
从不同的角度,进程可以有不同的定义,较典型的定义有以下:
定义1:
进程是具有独立功能的程序在数据集合上运行的一次执行过程,是系统进行资源分配和调度的一个独立单位。
定义2:
进程是进程实体的运行过程,是系统进行资源分配和调度的独立单位
1.动态性,动态性是指进程的创建、运行、暂停、终止等过程,动态性是进程最基本的特性
2.并发性,并发性指多个进程能够同时存在于内存中,能够在同一段时间内同时运行
3.独立性,独立性是指进程实体是一个能独立运行、独立获得资源和独立接收调度的基本单位,未创建PCB的程序,都不能作为一个独立的单位参与运行
4.异步性,异步性是指进程按照各自独立的、不可预知的速度向前推进,异步性会导致执行结果的不可再现性,因此在操作系统中要配置相应的进程同步机制
5.结构性,结构性是指进程由程序段、数据、PCB三部分组成的
1.创建进程实际上是创建进程的PCB。同样,撤销进程实际上是撤销进程的PCB,因此PCB是进程存在的唯一标志
2.进程实体是静态的,进程是动态的
引入线程的目的是为了减少程序在并发执行时所付出的时空开销(多个线程在同一个进程之间的切换),从而提高操作系统的并发性能
线程最直接的理解就是轻量级的进程,是CPU执行的最小单位。
线程是进程的一个实体,是CPU调度和分派的基本单位
1.线程不拥有系统资源,只拥有一点儿在运行中必不可少的资源,如线程的标识符和线程控制块(线程控制块记录了线程执行的寄存器和栈等现场状态)
2.同一个进程中的线程共享该进程拥有的资源
协程是一种用户态的轻量级线程,协程的调度完全由用户控制
协程有极高的执行效率,因为子程序不是线程切换,不需要切换上下文
资源分配给进程,同一进程的所有线程共享该进程的所有资源;
处理机分给线程,真正在处理机上运行的是线程
1.线程进程都是同步机制,而协程则是异步
2.协程的调度完全由用户控制,进程线程的调度由操作系统控制
3.上下文切换的速度(由高到低):协程>线程>进程
4.创建的大小(由小到大):协程>线程>进程
线程的好处:
可以大大的加快执行的速度,让其一起执行
以获取网页为例子:
#####装饰器获取执行的时间
import time
def cost(func):
def _cost(*args,**kwargs):
start=time.time()
result=func(*args,**kwargs)
end=time.time()
print("cost time:",end-start)
return result
return _cost
#####抓取网页
import requests
def get_content(url):
text=requests.get(url).content
time.sleep(0.5)
print("get content")
@cost
def main():
urls=["https://www.baidu.com/","https://www.baidu.com/","https://www.baidu.com/","https://www.baidu.com/","https://www.baidu.com/","https://www.baidu.com/"]
for url in urls:
get_content(url)
if __name__=="__main__":
main()
运行结果:
可以看到,没有使用子线程,只有一个主线程的运行时间需要4秒多,因为抓取网页了6次,每一次都休眠5秒,所以就相当于要重复执行6次抓取网页的操作。但是使用多线程并行,让其一起执行就只需要抓取一次网页的时间。就相当于有6个程序,每一个程序去抓取一个网页。
#####装饰器获取执行的时间
import time
def cost(func):
def _cost(*args,**kwargs):
start=time.time()
result=func(*args,**kwargs)
end=time.time()
print("cost time:",end-start)
return result
return _cost
import requests
from threading import Thread #导入创建线程的模块
###抓取网页
def get_content(url):
text = requests.get(url).content
time.sleep(0.5)
print("get content")
@cost
def main():
urls = ["https://www.baidu.com/", "https://www.baidu.com/", "https://www.baidu.com/", "https://www.baidu.com/",
"https://www.baidu.com/", "https://www.baidu.com/"]
t_list=[]
for url in urls:
###Thread(group.target,name,args,kwargs) ##group是线程组,target是指定要执行的方法、name是创建线程的名字、args和kwargs是传入的参数(元组和字典形式)
t=Thread(target=get_content,args=(url,)) #创建线程
t.start() #启动线程
t_list.append(t)
for t in t_list:
t.join() #相当于wait(),功能是阻塞当前环境的线程,让其等待子线程一起执行完毕才能执行后面的代码
if __name__ == "__main__":
main()
运行结果:
t.join的功能相当于linux中的wait,作用是让当前的进程等待创建的子线程执行完毕之后,再继续执行后续的代码。这样可以避免子进程未运行结束而父进程已经结束,并发送hup信号给内核,让其结束进程本身以及由该进程创建的一系列的子进程