python是单线程的,多线程有意义么

经常遇到小伙伴提到python是单线程的,写代码的时候用多线程没有意义,今天与大家分享一下关于python的单线程与多线程相关理解。

首先 python是单线程的 这句话是不对的。

这里要提到一个概念:Python的全局解释器锁(GIL)

GIL是什么

需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL

帮python洗白了这个冤屈之后我们继续看为什么要用多线程

import threading
import time


def test1():
    for i in range(100000000):
        a = 100 - i


def test2():
    threads = []
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test1)
    t3 = threading.Thread(target=test1)
    t4 = threading.Thread(target=test1)
    threads.append(t1)
    threads.append(t2)
    threads.append(t3)
    threads.append(t4)

    threads[0].start()
    threads[1].start()
    threads[2].start()
    threads[3].start()

    threads[0].join()
    threads[1].join()
    threads[2].join()
    threads[3].join()


if __name__ == '__main__':
    t1 = time.time()
    test1()
    print('单线程一次:', time.time() - t1)  # 单线程一次: 3.872997760772705
    test1()
    print('单线程两次:', time.time() - t1)  # 单线程两次: 7.738230466842651
    test1()
    print('单线程三次:', time.time() - t1)  # 单线程三次: 11.609771013259888
    test1()
    print('单线程四次:', time.time() - t1)  # 单线程四次: 15.493367433547974
    t2 = time.time()
    test2()
    print('多线程四次:', time.time() - t2)  # 多线程四次: 15.55045747756958

这段代码执行后会发现4个线程同时执行所消耗的时间与一个线程执行消耗的时间是几乎一样的,到这里有的人会吐槽,这多线程也没提高效率,毛用没有。事实上python多线程在提高效率这块确实毛用没有。因为上边说了,GIL的存在,与单线程处理效率是一样的。

本质是这4个线程交替轮番执行,你执行一会儿,我执行一会儿,他执行一会儿…就是非常和谐的随机在单核上执行

那么问题来了:

是不是python就不需要多线程了呢?

答案是:

需要

追问:

那有啥用呢?

在python里多线程最开始就不是用来解决多核利用率问题的,这个交给操作系统就好了,多线程是解决IO阻塞问题IO占用时CPU闲置问题
举个简单的例子:
有一个应用有三个接口:

接口A处理需要花费10s(注意是纯粹的cpu处理消耗时间,不包含网络通信等消耗时间)

接口B处理需要花费5s(注意是纯粹的cpu处理消耗时间,不包含网络通信等消耗时间)

接口C处理需要花费2s(注意是纯粹的cpu处理消耗时间,不包含网络通信等消耗时间)

如果三个用户:小红,小明,小张
几乎同时,小红请求和A接口,小明请求了B接口,小张请求了C接口

单线程下:

小红10s收到结果,小明15s收到结果,小张17s收到结果
小张的接口虽然很快,只需要2s(相对很快),但在单线程上要等前边小红,小明的处理完才能轮到他,所以他要等待17s才能收到结果,小张很郁闷,这么快的方法为啥要等这么长,所以这种设计明显是有问题的。

多线程下:

小红13s收到结果,小明7s收到结果,小张3s收到结果(三个方法交替轮番执行,数值是约等于)
这样虽然都慢一点,但小张和小明还是能接受的

结论:多线程使程序交替轮番执行,不会对后边的程序产生阻塞(这才是python应用多线程的根本目的)

补充:多线程提升不了CPU的处理效率,只能提供调用CPU的方案

所以如果运行瓶颈不在CPU运算而是在IO(网络)上,多线程显然很划算

总结:通常来说,多线程是一个好东西。不过,由于Python的GIL的限制,多线程更适合于I/O密集型应用(I/O释放了GIL,可以允许更多的并发),而不是计算密集型应用。对于后一种情况而言,为了实现更好地并行性,你需要使用多进程,以便让CPU的其他内核来执行。

以上就是我对python应用多线程的理解,有错误和不明确的地方欢迎大家留言!谢谢~

### Python 多线程单线程的区别及实现机制 #### 1. 单线程的定义及其特点 Python 中的单线程是指整个程序只在一个线程中运行,所有的任务按照顺序依次执行。这意味着如果某个任务耗时较长(如 I/O 操作),它会阻塞后续的任务直到完成为止[^1]。 以下是单线程的一个简单例子: ```python import time def say_hello(): print("今天又是美好的一天") time.sleep(1) for i in range(5): say_hello() ``` 在这个例子中,`say_hello()` 函数会被调用五次,每次都会等待一秒再继续下一次循环。 --- #### 2. 多线程的概念及其优点和缺点 多线程允许一个程序在同一时间运行多个线程,每个线程都可以独立地执行不同的任务。这通常用于处理高延迟的操作(如文件读写、网络请求等)。然而,由于 Python 的 GIL(全局解释器锁)的存在,真正的 CPU 密集型任务并不能通过多线程来加速[^3]。 ##### 多线程的优点 - 提升响应速度:对于涉及大量 I/O 阻塞的应用场景(如网络爬虫、日志记录等),多线程可以显著提升程序的整体响应能力。 - 资源共享方便:同一进程内的线程共享内存空间,便于数据交换和通信[^2]。 ##### 多线程的缺点 - 线程切换开销大:频繁的上下文切换可能导致额外的时间消耗。 - 并发控制复杂:需要考虑竞态条件、死锁等问题,增加了开发难度。 --- #### 3. Python 多线程的实现方式 Python 提供了 `threading` 模块来支持多线程编程。下面是一个简单的多线程示例: ```python import threading import time def say_hello(): print(f"{threading.current_thread().name} 开始工作") time.sleep(1) print(f"{threading.current_thread().name} 完成") threads = [] for i in range(5): t = threading.Thread(target=say_hello, name=f"Thread-{i}") threads.append(t) t.start() for t in threads: t.join() # 主线程等待子线程结束 ``` 上述代码创建了五个线程,它们几乎同时启动并分别打印自己的名称以及状态信息。 需要注意的是,尽管这些线程看似并行运行,但由于 GIL 的存在,实际上只有当某些线程处于 I/O 阻塞状态时其他线程才能获得执行机会[^4]。 --- #### 4. 单线程 vs 多线程的主要区别 | 特性 | 单线程 | 多线程 | |---------------------|-------------------------------------|---------------------------------------| | **并发性** | 不具备真正意义上的并发 | 可以实现一定程度上的并发 | | **资源占用** | 较少 | 更多(因为有额外的线程管理成本) | | **适用场景** | 计算密集型任务 | I/O 密集型任务 | | **复杂度** | 简单 | 增加(需注意同步问题) | --- #### 5. 总结 虽然 Python 支持多线程编程,但在实际应用中其效果可能受到 GIL 的限制而不如预期那样高效。因此,在选择是否采用多线程方案之前应充分评估具体需求,并权衡利弊。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值