通俗易懂的进程,线程和协程讲解

进程,线程,协程

概念

  • 进程和线程

    • 进程就是一个程序在一个数据集上的一次动态执行过程(数据集是程序在执行过程中所需要使用的资源)。
    • 线程也叫轻量级进程,它是一个基本的 CPU 执行单元,是比进程更小的能独立运行的基本单位。
    • 进程和线程的关系:
      • 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
      • 资源分配给进程,同一进程的所有线程共享该进程的所有资源。
      • CPU 分给线程,即真正在 CPU 上运行的是线程。
  • 并行和并发

    • 并行处理是计算机系统中能同时执行两个或更多个处理的一种计算方法。并行处理可同时工作于同一程序的不同方面,其主要目的是节省解决大型和复杂问题的时间。
    • 并发处理指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个 CPU 上运行,但任一个时刻点上只有一个程序在 CPU 上运行。
    • 对于一个支持多进程的系统,CPU 会从一个进程快速切换至另一个进程,其间每个进程各运行几十或几百个毫秒。虽然单核的 CPU 在某一个瞬间,只能运行一个进程。但在 1 秒钟期间,它可能会运行多个进程,这样就产生并行的错觉,实际上这是并发。
    • 并发的关键是你有处理多个任务的能力,不一定要同时。并行的关键是你有同时处理多个任务的能力。所以说,并行是并发的子集。多进程是并行的,多线程是并发的。
      在这里插入图片描述
  • 同步和异步

    • 同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去。
    • 异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
    • 举个例子,打电话时就是同步通信,发短息时就是异步通信。

比较

我们来比较一下三者的区别及应用场景。

进程线程协程
特点及优势进程是资源分配的单位;
进程切换需要的资源最大,效率很低,但有利于资源的保护和管理;
进程在执行过程中拥有独立的内存单元;
一个子进程崩溃并不会影响其他子进程和主进程的运行
线程是操作系统调度的单位;
线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下);
多个线程共享内存,从而极大地提高了程序的运行效率;
切换快,资源消耗低
协程切换任务资源很小,效率高;
对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序;
避免无意义调度从而提高性能;
高并发+高扩展性+低成本
缺点不能一次性启动太多进程,会严重影响系统的资源调度一个线程挂掉则会影响到所有线程,所以不够稳定无法利用多核资源;进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
常用库multiprocessing库threading库:线程池gevent库
asyncio库
并行or并发多进程、多线程根据cpu核数不一样可能是并行的多进程、多线程根据cpu核数不一样可能是并行的协程是在一个线程中,所以是并发;单线程异步
适用场景多进程适合在 CPU 密集型操作或计算密集型(cpu 操作指令比较多,如位数多的浮点运算)。多线程适合在 IO 密集型操作(读写数据操作较多的,比如爬虫)当程序中存在大量不需要CPU的操作时(IO),适用于协程;
强调非阻塞异步并发的一般都是使用协程;Web应用

比较通俗的理解

进程、线程、协程对比 :请仔细理解如下的通俗描述
• 有一个老板想要开个工厂进行生产某件商品(例如剪子)
• 他需要花一些财力物力制作一条生产线,这个生产线上有很多的器件以及材料这些所有的为了能够生产剪子而准备的资源称之为:进程
• 只有生产线是不能够进行生产的,所以老板的找个工人来进行生产,这个工人能够利用这些材料最终一步步的将剪子做出来,这个来做事情的工人称之为:线程
• 这个老板为了提高生产率,想到3种办法:

  1. 在这条生产线上多招些工人,一起来做剪子,这样效率是成倍増长,即单进程 多线程方式
  2. 老板发现这条生产线上的工人不是越多越好,因为一条生产线的资源以及材料毕竟有限,所以老板又花了些财力物力购置了另外一条生产线,然后再招些工人这样效率又再一步提高了,即多进程 多线程方式
  3. 老板发现,现在已经有了很多条生产线,并且每条生产线上已经有很多工人了(即程序是多进程的,每个进程中又有多个线程),为了再次提高效率,老板想了个损招,规定:如果某个员工在上班时临时没事或者再等待某些条件(比如等待另一个工人生产完某道工序 之后他才能再次工作) ,那么这个员工就利用这个时间去做其它的事情,那么也就是说:如果一个线程等待某些条件,可以充分利用这个时间去做其它事情,其实这就是:协程方式

测试

  • 准备工作:创建一个APP,延迟3秒后输出‘hello’.
from flask import Flask     # pip install flask
import time

app = Flask(__name__)

@app.route('/')
def index():
    time.sleep(3)    		# 休眠 3 秒再返回结果
    return 'Hello!'

if __name__ == '__main__':
    app.run(threaded=True)  # 以多线程模式启动服务
  • 测试
import requests
import time
# 用于多进程
from multiprocessing import Process
# 用于多线程
from threading import Thread
# 用于协程+异步
import asyncio
import aiohttp      # pip install aiohttp

urls = ['http://127.0.0.1:5000' for _ in range(10)]

def get_html_text(url):
    response = requests.get(url)
    return response.text

# 单进程
start = time.time()
for url in urls:
    result = get_html_text(url)
    print(result)
end = time.time()
print('【单进程单线程】耗时:%s 秒' %(end - start))

# 多进程 + 并行
start = time.time()
processes = []
for url in urls:
    p = Process(target=get_html_text, args=(url,))
    processes.append(p)
    p.start()
for p in processes:
    p.join()
    print('Hello!')
end = time.time()
print('【多进程  并行】耗时:%s 秒' %(end - start))

# 多线程 + 并发
start = time.time()
threads = []
for url in urls:
    t = Thread(target=get_html_text, args=(url,))
    threads.append(t)
    t.start()
for t in threads:
    t.join()
    print('Hello!')
end = time.time()
print('【多线程  并发】耗时:%s 秒' %(end - start))

# 协程 + 异步
# 因为 requests 模块不支持异步操作,需要借助 aiohttp 模块
async def get_html_text_async(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            text = await response.text()
            return text

start = time.time()
tasks = [asyncio.ensure_future(get_html_text_async(url)) for url in urls]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
for task in tasks:
    print(task.result())
end = time.time()
print('【协程 ++ 异步】耗时:%s 秒' %(end - start))

  • 执行结果
【单进程单线程】耗时:30.076159238815308 秒
【多进程  并行】耗时:31.149558782577515 秒
【多线程  并发】耗时:3.0131824016571045 秒
【协程 ++ 异步】耗时:3.0092201232910156

解释

  • 单进程单线程 是将 n 次请求顺次执行,每次要等待 3 秒才能返回结果,故耗时 3n+ 秒;
  • 多进程-并行 处理则利用 CPU 的多核优势,在同一时间并行地执行多个任务,可以大大提高执行效率,但系统实现多进程前需要一些准备工作、将耗费大量时间。
  • 多线程-并发处理协程+异步 的耗时由单进程单线程的 3n+ 秒变成了 3+ 秒!
    • 前者是 n 个请求几乎同时进行、几乎同时得到响应返回结果。
    • 后者是每当请求任务遇到阻塞(time.sleep(3))时被挂起,n 个任务都处于挂起状态后等待 3 秒,n 个请求几乎同时都有了响应,然后挂起的任务被唤醒接着执行,输出请求结果,最后耗时:3 秒!(多出来的时间是 IO 时延)
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值