在python中单线程,多线程,多进程对CPU的利用率实测以及GIL原理分析

简介: 首先关于在python中单线程,多线程,多进程对cpu的利用率实测如下: 单线程,多线程,多进程测试代码使用死循环。 1)单线程: 2)多线程: 3)多进程: 查看cpu使用效率: 开始观察分别执行时候cpu的使用效率:1)单线程执行的时候: 2)多线程执行的时候: 3)多进程执行的时候: 总结:1)单进程单线程时,对于双核CPU的利用率只能利用一个核,没有充分利用两个核。

首先关于在python中单线程,多线程,多进程对cpu的利用率实测如下:

 

单线程,多线程,多进程测试代码使用死循环。

 

1)单线程:

 

2)多线程:

 

3)多进程:

 

查看cpu使用效率:

 

开始观察分别执行时候cpu的使用效率:

1)单线程执行的时候:

 

2)多线程执行的时候:

 

3)多进程执行的时候:

 

总结:

1)单进程单线程时,对于双核CPU的利用率只能利用一个核,没有充分利用两个核。

2)单进程多线程时,对于双核CPU的来说,虽然两个核都用到的,不过很明显没有充分利用两个核,这里要说一个GIL(全局解释器锁)的概念:

GIL不同于线程之间的互斥锁,GIL并不是Python的特性,而是Cpython引入的一个概念。(Jpython,PYPY)

Python的代码由Python的解释器执行(CPython)。那么我们的代码什么时候被python解释器执行,由我们的GIL也就是全局解释器锁进行控制。

当我们有一个线程开始访问解释器的时候,GIL会将这把锁上锁,也就是说,其他线程无法再访问解释器,也就意味着,其他的线程无法再被执行。

 

GIL执行流程:

 

  1. 加锁GIL

  2. 切换到一个线程去执行。

  3. 运行。

  4. 解锁GIL

再次重复以上步骤。

对于下列代码GIL的执行流程:

 

import threading
import time
# 写两个函数,分别让两个线程去执行
# 这个两个函数,都要访问我的全局变量
number = 0

def test1(count):
    global number
    for i in range(count):
        number += 1
    print(number)

def test2(count):
    global number
    for i in range(count):
        number += 1
    print(number)


def main():
    th1 = threading.Thread(target=test1,args= (1000000,))
    th2 = threading.Thread(target=test2, args=(1000000,))
    th1.start()
    th2.start()

    time.sleep(5)
    print(number)

if __name__ == '__main__':
    main()

 

运行结果(这里充分的说明了多线程资源抢占问题):

流程图如下:

线程1在执行到对全局变量加一操作的时候全局解释器锁被收回,线程2申请并得到了全局解释器锁开始运行,在线程2执行完加一操作以后对全局变量进行了修改并释放了全局解释器锁。

这时线程1再次得到了全局解释器锁,从上次释放全局解释器锁的地方开始继续执行对全局变量加一的操作,记住,这里线程1中的全局变量还是开始的0,虽然线程2已经对其进行了加一的操作,但是线程1并不知道,线程1还是会接着上一次的位置开始执行,所以线程1在执行完加一操作的时候同样把1再次赋值给了全局变量num,也就是说,线程2执行完加一操作之后赋值过去的1又被线程1赋值过去的1所覆盖,加了两次等于加了一次!类似于协程,只是做了一个执行代码来回切换的操作!

所以在Python中,同一时刻,只能有一个线程被执行。所以Python中的多线程是假的

既然这样我们为什么还要用多线程呢?

其实多线程也有它的好处,例如我们在进行IO操作的时候,有效的组织了程序的阻塞,不至于一直无限的等待。

3)多进程时,对于双核CPU来说,每个进程的优先级都是同等的,所分配的资源也是相等的,两个进程的时候完全可以充分的利用双核CPU,而且由于计算密集型的任务完全是依靠于cpu的核数,所以需要尽量的完全利用cpu,这时候多进程的好处就能够完美的体现出来。

 

 

                                                                   -------  知识无价,汗水有情,如需搬运请注明出处,谢谢!

目录
相关文章
schedule:原来还可以这样让进程让出 CPU?
文章主要讲述通过模拟时钟中断和调度事件来优化和测试虚拟机监控器(VMM)的方法,包括流程设计、寄存器状态的保存与恢复、硬件中断处理规范等细节。
schedule:原来还可以这样让进程让出 CPU?
taosd 写入与查询场景下压缩解压及加密解密的 CPU 占用分析
在当今大数据时代,时序数据库的应用越来越广泛,尤其是在物联网、工业监控、金融分析等领域。TDengine 作为一款高性能的时序数据库,凭借独特的存储架构和高效的压缩算法,在存储和查询效率上表现出色。然而,随着数据规模的不断增长,在保证数据安全性和存储效率的同时,如何优化 CPU 的资源占用,成为了一个值得深入讨论的问题。
48 1
我是如何通过火焰图分析让应用CPU占用下降近20%的
分享作者在使用Arthas火焰图工具进行Java应用性能分析和优化的经验。
|
7月前
线程CPU异常定位分析
【10月更文挑战第3天】 开发过程中会出现一些CPU异常升高的问题,想要定位到具体的位置就需要一系列的分析,记录一些分析手段。
180 0
构建高效Python应用:并发与异步编程的实战秘籍,IO与CPU密集型任务一网打尽!
在Python编程的征途中,面对日益增长的性能需求,如何构建高效的应用成为了每位开发者必须面对的课题。并发与异步编程作为提升程序性能的两大法宝,在处理IO密集型与CPU密集型任务时展现出了巨大的潜力。今天,我们将深入探讨这些技术的最佳实践,助你打造高效Python应用。
99 0
Python实用技巧:轻松驾驭多线程与多进程,加速任务执行
在Python编程中,多线程和多进程是提升程序效率的关键工具。多线程适用于I/O密集型任务,如文件读写、网络请求;多进程则适合CPU密集型任务,如科学计算、图像处理。本文详细介绍这两种并发编程方式的基本用法及应用场景,并通过实例代码展示如何使用threading、multiprocessing模块及线程池、进程池来优化程序性能。结合实际案例,帮助读者掌握并发编程技巧,提高程序执行速度和资源利用率。
84 0
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
70 6
别让你的CPU打盹儿:Apache Doris并行执行原理大揭秘!
别让你的CPU打盹儿:Apache Doris并行执行原理大揭秘!
229 1
别让你的CPU打盹儿:Apache Doris并行执行原理大揭秘!
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
6月前
|
dllhost.exe进程占用CPU很高怎么解决?
全面解析dllhost.exe进程
366 16