我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python并发编程多进程,多线程及GIL全局解释器锁

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python并发编程多进程,多线程及GIL全局解释器锁

1. 并发与并行

  • 所谓的并行(Parallelism),就是多个彼此独立的任务可以同时一起执行,彼此并不相互干扰,并行强调的是同时且独立的运行,彼此不需要协作。
  • 而所谓并发(Concurrency),则是多个任务彼此交替执行,但是同一时间只能有一个处于运行状态,并发执行强调任务之间的彼此协作。

并发通常被误解为并行,并发实际是隐式的调度独立的代码,以协作的方式运行。比如在等待IO线程完成IO操作之前,可以启动IO线程之外的其他独立代码同步执行其他操作。

关于并发、并行的图示,如下:

由于CPython解释器中的全局解释器锁(GIL,Global Interpreter Lock)的存在,所以Python中的并行实际上是一种假并行,并不是真正意义上的同时独立运行。

2. 线程与进程的应用场景

进程(Process)是操作系统层面的一个抽象概念,它是运行代码创建出来的、加载到内存中运行的程序。电脑上通常运行着多个进程,这些进程之间是彼此独立运行的。

线程(Thread)是操作系统可以调度的最小运行程序单位,其包含在进程中,一个进程中通常至少包含1个线程,一些进程中会包含多个线程。多个线程运行的都是父进程的相同代码,理想情况下,这些线程是并行执行的,但由于GIL的存在,所以它们实际上是交替执行的,并不是真正意义上的独立、并行的执行的。

下表是进程与线程的对比:

对于IO密集型的操作,更适合使用多线程编程的方式来解决问题;对于CPU密集型的操作,则更适合使用多进程编程的方式来解决问题。

2.1. 并行/并发编程相关的技术栈

Python中提供了一些模块用于实现并行/并发编程,具体如下所示:

threading:Python中进行多线程编程的标准库,是一个对_thread进行再封装的高级模块。multiprocessing:类似于threading模块,提供的API接口也与threading模块类似,不同的是它进行多进程编程。concurrent.futures:标准库中的一个模块,在线程编程模块的基础上抽象出来的更高级实现,且该模块的编程为异步模式。queue:任务队列模块,queue中提供的队列是线程安全的,所以可以使用这个模块进行线程之间进行安全的数据交换操作。不支持分布式。celery:一个高级的分布式任务队列,通过multiprocessing模块或者gevent模块可以实现队列中人物的并发执行。支持多节点之间的分布式计算。 2.2. 通过编码比较多进程与多线程的执行效果

在下面的代码中,定义了两个函数:only_sleep()以及crunch_numbers(),前者用于模拟IO密集型操作(需要频繁中断),后者用于模拟CPU密集型操作。

然后在串行调用、多线程的方式调用、多进程的方式调用,三种不同的执行环境中,比较各个函数的执行效率情况。

具体代码以及执行结果如下所示:

import time
import datetime
import logging
import threading
import multiprocessing

FORMAT = "%(asctime)s [%(processName)s %(process)d] %(threadName)s %(thread)d <=%(message)s=>"
logging.basicConfig(format=FORMAT, level=logging.INFO, datefmt='%H:%M:%S')
def only_sleep():
	"""
	模拟IO阻塞型操作,此时多线程优势明显

	:return:
	"""
	logging.info('in only_sleep function')
	time.sleep(1)
def crunch_numbers():
	"""
	模拟CPU密集型操作,此时多进程优势明显
	:return:
	"""
	logging.info('in crunch_numbers function')
	x = 0
	while x < 1000000:
    	x += 1
if __name__ == '__main__':
	work_repeat = 4
	print('==>> only_sleep function test')
	count = 0
	for func in (only_sleep, crunch_numbers):
    	count += 1
	    # run tasks serially
    	start1 = datetime.datetime.now()
	    for i in range(work_repeat):
    	    func()
	    stop1 = datetime.datetime.now()
    	delta1 = (stop1 - start1).total_seconds()
	    print('Serial Execution takes {} seconds~'.format(delta1))

    	# run tasks with multi-threads
	    start2 = datetime.datetime.now()
    	thread_lst = [threading.Thread(target=func, name='thread-worker' + str(i)) for i in range(work_repeat)]
	    [thd.start() for thd in thread_lst]
    	[thd.join() for thd in thread_lst]
	    stop2 = datetime.datetime.now()
    	delta2 = (stop2 - start2).total_seconds()
	    print('Multi-Threads takes {} seconds~'.format(delta2))
    	# run tasks with multiprocessing
	    start3 = datetime.datetime.now()
    	proc_lst = [multiprocessing.Process(target=func, name='process-worker' + str(i)) for i in range(work_repeat)]
	    [thd.start() for thd in proc_lst]
    	[thd.join() for thd in proc_lst]
	    stop3 = datetime.datetime.now()
    	delta3 = (stop3 - start3).total_seconds()
	    print('Multi-Processing takes {} seconds~'.format(delta3))
    	if count == 1:
        	print('\n', '*.' * 30, end='\n\n')
	        print('==>> crunch_numbers function test')

上述代码的执行结果如下:

23:55:51 [MainProcess 568124] MainThread 182168 <=in only_sleep function=>
==>> only_sleep function test
23:55:52 [MainProcess 568124] MainThread 182168 <=in only_sleep function=>
23:55:53 [MainProcess 568124] MainThread 182168 <=in only_sleep function=>
23:55:54 [MainProcess 568124] MainThread 182168 <=in only_sleep function=>
23:55:55 [MainProcess 568124] thread-worker0 553012 <=in only_sleep function=>
23:55:55 [MainProcess 568124] thread-worker1 567212 <=in only_sleep function=>
23:55:55 [MainProcess 568124] thread-worker2 547252 <=in only_sleep function=>
23:55:55 [MainProcess 568124] thread-worker3 561892 <=in only_sleep function=>
Serial Execution takes 4.022761 seconds~
Multi-Threads takes 1.01416 seconds~
23:55:56 [process-worker0 563068] MainThread 567480 <=in only_sleep function=>
23:55:56 [process-worker1 567080] MainThread 567628 <=in only_sleep function=>
23:55:56 [process-worker2 567868] MainThread 563656 <=in only_sleep function=>
23:55:56 [process-worker3 567444] MainThread 566436 <=in only_sleep function=>
23:55:57 [MainProcess 568124] MainThread 182168 <=in crunch_numbers function=>
Multi-Processing takes 1.11466 seconds~

*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.

==>> crunch_numbers function test
23:55:57 [MainProcess 568124] MainThread 182168 <=in crunch_numbers function=>
23:55:57 [MainProcess 568124] MainThread 182168 <=in crunch_numbers function=>
23:55:57 [MainProcess 568124] MainThread 182168 <=in crunch_numbers function=>
Serial Execution takes 0.1786 seconds~
23:55:57 [MainProcess 568124] thread-worker0 567412 <=in crunch_numbers function=>
23:55:57 [MainProcess 568124] thread-worker1 566468 <=in crunch_numbers function=>
23:55:57 [MainProcess 568124] thread-worker2 565272 <=in crunch_numbers function=>
23:55:57 [MainProcess 568124] thread-worker3 568044 <=in crunch_numbers function=>
Multi-Threads takes 0.195057 seconds~
23:55:58 [process-worker0 567652] MainThread 561892 <=in crunch_numbers function=>
23:55:58 [process-worker1 553012] MainThread 547252 <=in crunch_numbers function=>
23:55:58 [process-worker2 554024] MainThread 556500 <=in crunch_numbers function=>
23:55:58 [process-worker3 565004] MainThread 566108 <=in crunch_numbers function=>
Multi-Processing takes 0.155246 seconds~

Process finished with exit code 0

从上述执行结果中可以看出:

上述代码的执行结果也验证了此前的结论:对于IO密集型操作,适合使用多线程编程的方式解决问题;而对于CPU密集型的操作,则适合使用多进程编程的方式解决问题。

3. Python中的GIL是什么,它影响什么

GIL是CPython中实现的全局解释器锁 (Global Interpreter Lock),由于CPython是使用最广泛的Python解释器,所以GIL也是Python世界中最饱受争议的一个主题。

GIL是互斥锁,其目的是为了确保线程安全,正是因为有了GIL,所以可以很方便的与外部非线程安全的模块或者库结合起来。但是这也是有代价的,由于有了GIL,所以导致Python中的并行并不是真正意义上的并行,所以也就无法同时创建两个使用相同代码段的线程,相同代码的线程只能有一个处于执行状态。因为GIL互斥锁,相同代码访问的数据会被加锁,只有当一个线程释放锁之后,相同代码的另一个线程才能访问未被加锁的数据。

所以Python中的多线程是相互交替执行的,并不是真正的并行执行的。但是在CPython之外的一些库,是可以实现真正意义上的并行的,比如numpy这个数据处理常用的库。

到此这篇关于Python并发编程多进程,多线程及GIL全局解释器锁的文章就介绍到这了,更多相关Python GIL解释器锁内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python并发编程多进程,多线程及GIL全局解释器锁

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python进程与线程及GIL(全局解释

MarkdownPad Document程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种一个程序在一个数据集上的一次动态执行过程就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;
2023-01-31

Python并发编程中的GIL,理解全局解释器锁对Python并发编程的影响

Python并发编程中的GIL,解读全局解释器锁对Python并发编程的影响 : Python、GIL、并发编程、多线程、性能 Python是一种解释型语言,它的解释器采用单线程模型,即在同一时间只能执行一条指令。为了解决这个问题,Python引入了全局解释器锁(GIL)的概念。GIL是一种同步机制,它确保在同一时间只能有一个线程执行Python字节码。
Python并发编程中的GIL,理解全局解释器锁对Python并发编程的影响
2024-02-05

Python 多线程与多进程:进阶指南,解锁并发编程的更多可能性

Python 多线程与多进程是两种重要的并发编程技术,它能够充分利用计算机的处理能力,提高程序的执行效率。本文将深入探讨 Python 多线程和多进程的原理、使用方式以及常见的应用场景,帮助你解锁并发编程的更多可能性。
Python 多线程与多进程:进阶指南,解锁并发编程的更多可能性
2024-02-24

揭秘Python GIL:多线程并发编程的拦路虎

Python GIL(全局解释器锁)是一个互斥锁,它确保同一时刻只有一个线程能够执行Python字节码。这限制了Python的多线程并发编程性能,但它也保证了Python解释器的稳定性和安全性。
揭秘Python GIL:多线程并发编程的拦路虎
2024-02-26

python并发编程之多进程、多线程、异步和协程详解

最近学习python并发,于是对多进程、多线程、异步和协程做了个总结。 一、多线程多线程就是允许一个进程内存在多个控制权,以便让多个函数同时处于激活状态,从而让多个函数的操作同时运行。即使是单CPU的计算机,也可以通过不停地在不同线程的指令
2022-06-04

Python并发编程:探索多线程和多进程的奥秘

探索Python并发编程的奥秘,掌握多线程与多进程魅力,释放程序性能新高度。 Python、并发编程、多线程、多进程、协程 在计算机科学领域,并发编程一直备受关注,它通过同时执行多个任务来提升程序性能,其中Python作为一门功能丰富的编程语言,也在并发编程方面提供了强大的支持。本文将深入探究Python并发编程,重点阐述多线程和多进程技术的原理与应用,帮助您掌握并发编程技巧,释放程序性能新高度。
Python并发编程:探索多线程和多进程的奥秘
2024-02-05

探索 Swoole 扩展的多进程和多线程并发编程,解锁并行处理的奥秘

探索 Swoole 扩展的多进程和多线程并行编程,掌握高并发应用开发技巧
探索 Swoole 扩展的多进程和多线程并发编程,解锁并行处理的奥秘
2024-02-05

Python 多线程与多进程:常见问题解答,扫除并发编程的障碍

Python的多线程与多进程是并发编程的基础,但它们可能会带来很多问题。本文将解答这些常见问题,扫除您并发编程的障碍。
Python 多线程与多进程:常见问题解答,扫除并发编程的障碍
2024-02-24

Python 多线程与多进程:深入浅出,轻松掌握高并发编程利器

Python 的多线程和多进程是强大的工具,可以帮助您编写出高效且可伸缩的应用程序。本文将深入浅出地介绍 Python 的多线程和多进程,让您轻松掌握高并发编程利器,显著提升代码执行效率。
Python 多线程与多进程:深入浅出,轻松掌握高并发编程利器
2024-02-24

Java多线程编程中的并发安全问题及解决方法

保障多线程并发安全,解决线程同步与锁竞争问题,提高应用性能与可靠性。多线程编程需要考虑线程安全性,使用同步机制保证共享变量的一致性,避免线程竞争导致的数据不一致与死锁等问题。常用的同步机制包括synchronized、ReentrantLock、volatile等
2023-05-16

计算机网络编程 | 并发服务器代码实现(多进程/多线程)

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学
2023-08-18

Python 多线程与多进程:揭秘并发编程的奥秘,提升代码性能

Python 多线程与多进程是并发编程的两个重要概念,它们可以极大地提升代码性能。它们之间的区别在于,多线程共享同一个内存空间,而多进程则拥有各自独立的内存空间。多线程更适合 I/O 密集型任务,而多进程更适合 CPU 密集型任务。
Python 多线程与多进程:揭秘并发编程的奥秘,提升代码性能
2024-02-24

Python 多线程与多进程:未来发展趋势,把握并发编程的前沿技术

并发编程是计算机科学中的重要技术,Python 多线程和多进程是常用的并发编程手段,在未来发展中具有广阔的前景。本文将介绍 Python 多线程和多进程的发展趋势,以及如何把握并发编程的前沿技术。
Python 多线程与多进程:未来发展趋势,把握并发编程的前沿技术
2024-02-24

Python 多线程与多进程:学习资源指南,快速掌握并发编程的精髓

Python 多线程与多进程是并发编程的基础,掌握这些知识可以显著提高程序的性能。本文提供了丰富的学习资源,包括教程、书籍、视频和项目,帮助您快速掌握并发编程的精髓。
Python 多线程与多进程:学习资源指南,快速掌握并发编程的精髓
2024-02-24

Python 多线程与多进程:实战案例剖析,掌握并发编程的应用技巧

Python 多线程、多进程是实现并发编程的两种主要方式,在实践中各有所长。本文将通过两个实战案例,深入剖析多线程、多进程的应用技巧,帮助开发者更好地掌握并发编程。
Python 多线程与多进程:实战案例剖析,掌握并发编程的应用技巧
2024-02-24

Python 多线程与多进程:行业应用实例,探索并发编程的无限潜力

Python多线程和多进程是两种强大的并发编程模式,它们可以帮助我们充分利用多核CPU的计算能力,大幅提升程序性能。多线程和多进程在行业中有着广泛的应用,本文将通过几个实例来展示它们在实际场景中的应用,帮助读者深入理解和掌握这些并发编程技术。
Python 多线程与多进程:行业应用实例,探索并发编程的无限潜力
2024-02-24

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录