python 线程,进程,协程

一、进程与线程

1.进程

我们电脑的应用程序,都是进程,假设我们用的电脑是单核的,cpu同时只能执行一个进程。当程序出于I/O阻塞的时候,CPU如果和程序一起等待,那就太浪费了,cpu会去执行其他的程序,此时就涉及到切换,切换前要保存上一个程序运行的状态,才能恢复,所以就需要有个东西来记录这个东西,就可以引出进程的概念了。

进程就是一个程序在一个数据集上的一次动态执行过程。进程由程序,数据集,进程控制块三部分组成。程序用来描述进程哪些功能以及如何完成;数据集是程序执行过程中所使用的资源;进程控制块用来保存程序运行的状态

2.线程

一个进程中可以开多个线程,为什么要有进程,而不做成线程呢?因为一个程序中,线程共享一套数据,如果都做成进程,每个进程独占一块内存,那这套数据就要复制好几份给每个程序,不合理,所以有了线程。

线程又叫轻量级进程,是一个基本的cpu执行单元,也是程序执行过程中的最小单元。一个进程最少也会有一个主线程,在主线程中通过threading模块,在开子线程

3.进程线程的关系

(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

(2)资源分配给进程,进程是程序的主体,同一进程的所有线程共享该进程的所有资源

(3)cpu分配给线程,即真正在cpu上运行的是线程

(4)线程是最小的执行单元,进程是最小的资源管理单元

4.并行和并发
并行处理是指计算机系统中能同时执行两个或多个任务的计算方法,并行处理可同时工作于同一程序的不同方面

并发处理是同一时间段内有几个程序都在一个cpu中处于运行状态,但任一时刻只有一个程序在cpu上运行。

并发的重点在于有处理多个任务的能力,不一定要同时;而并行的重点在于就是有同时处理多个任务的能力。并行是并发的子集

以上所说的是相对于所有语言来说的,Python的特殊之处在于Python有一把GIL锁,这把锁限制了同一时间内一个进程只能有一个线程能使用cpu

二 协程:

协程,又称微线程,纤程。英文名Coroutine。协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。

1、子程序,或者称为函数。在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。子程序调用总是一个入口,一次返回,调用顺序是明确的。

顺序执行的缺点:这里小伙伴们都应该是分清楚,那就是程序的无休止等待,必须等待一个函数执行完之后才返回结果。 

2、多线程。避免顺序执行的方式之一是多线程,但是考虑到python语言的特性(GIL锁),再执行计算密集型的任务时,多线程的执行效果反而变慢,再执行IO密集型的任务时候虽然有不错的性能提升,但是依然会有线程管理与切换、同步的开销等等(具体原因这里不详细说明,请参见相关的GIL说明)

3、协程。协程有点像多线程,但协程的特点在于是一个线程执行,那和多线程比,协程有何优势?

优势一:最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

优势二:就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

4、多进程+协程。因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

5、协程与一般函数的不同点

协程看上去也是子程序(函数),但执行过程中,在子程序内部(函数)可中断,而不是一次性一定要执行完才行,然后转而执行别的子程序,在适当的时候再返回来接着执行。 

 

多线程

from threading import Thread

def fun():
    for i in range(1000):
        print("子线程", i)

if __name__=='__main__':
    t = Thread(target=fun)
    t.start()
    for i in range(1000):
        print("主线程", i)

多进程

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

def fun(name):
    for i in range(1000000):
        print(name,i)


if __name__=='__main__':
    with ThreadPoolExecutor(50) as t:
        for i in range(1000000):
        for i in range(1000000):
            t.submit(fun,name=f"线程{i}")
    print("over")

协程

import asyncio
import time


async def fun1():
    print("123")
    await asyncio.sleep(3)
    print("123")

async def fun2():
    print("456")
    await asyncio.sleep(4)
    print("456")

async def fun3():
    print("789")
    await asyncio.sleep(5)
    print("789")

async def main():
    takes = [
        fun1(),
        fun2(),
        fun3(),
    ]
    await asyncio.wait((takes))

if __name__=="__main__":
    t1 = time.time()
    asyncio.run(main())
    t2 = time.time()
    print(t2-t1)

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天行九歌。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值