Python多线程与GIL锁
2023/4/9 11:22:00
本文主要是介绍Python多线程与GIL锁,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Python多线程与GIL锁
python多线程
Python的多线程编程可以在单个进程内创建多个线程来同时执行多个任务,从而提高程序的效率和性能。Python的多线程实现依赖于操作系统的线程调度器,并且受到全局解释器锁(GIL)的限制,因此在某些情况下,多线程并不能真正实现并行执行。
import threading def print_numbers(): for i in range(1, 6): print(i) thread1 = threading.Thread(target=print_numbers) thread2 = threading.Thread(target=print_numbers) thread1.start() thread2.start() thread1.join() thread2.join() print("Done")
上述代码创建了两个线程分别同时去打印1-5数字,但是即使有多个cpu,同一时刻也只能打印一个数字!why?
这是由于Python中的全局解释器锁(GIL)导致的。GIL是一种机制,用于确保在任何给定时间内,只有一个线程在Python解释器中执行字节码。这意味着无论有多少个CPU核心,每个线程都无法并行执行Python字节码。因此在执行CPU密集型任务时,多个线程之间的执行是交替进行的,而不是并行的。因此对于CPU任务,python的多线程是假的。而对于IO任务,确实是真正的多线程。
GIL锁
GIL的存在主要是为了防止Python解释器中的数据结构被多个线程同时修改,导致数据结构出现不一致的情况。通过限制同一时刻只有一个线程能够执行Python字节码,GIL可以确保Python解释器中的数据结构不会被多个线程同时修改,从而保证线程安全。
IO任务
I/O资源(Input/Output resources),是指计算机系统中用于输入输出数据的设备和接口,例如硬盘、网络接口、键盘、鼠标等。在计算机编程中,I/O操作指的是程序和外部设备之间进行的数据传输和交互,如读取文件、网络传输,爬虫等。I/O操作通常是非常耗时的,因为它们需要等待外部设备响应或者等待数据的读取。
这些IO任务通常只占用内存和网络,不占用CPU资源,所以也不占用python解释器,因此如果是IO密集型任务,python的多线程优势才能体现出来,而CPU密集型任务python的多线程效率无法有效提升。
破解GIL锁的限制
如果需要处理CPU密集型任务,可以考虑使用多进程编程,因为在多进程中,每个进程都有自己的解释器和内存空间,从而避免了GIL的限制。可以充分利用多核处理器(必须是真正的多核处理器才能体现,否则还是单进程)的优势。
python多进程
使用Python多进程编程的一般步骤如下:
- 导入multiprocessing模块,创建进程池对象。可以通过Pool()函数创建进程池对象,指定最大进程数。
- 定义需要执行的任务函数。这个函数应该能够接受任务参数,处理任务,返回任务结果。
- 调用进程池对象的map()函数,传入任务函数和任务参数。该函数会将任务参数分配给进程池中的进程执行,并返回任务结果列表。
- 处理任务结果。根据任务函数的返回值,对任务结果进行处理。可以使用Python中的其他模块,如pandas、numpy等进行数据处理或结果可视化。
需要注意的是,在Python中使用多进程编程时,进程之间的通信和同步是需要考虑的问题。Python中的multiprocessing模块提供了一些同步原语,如Lock、Semaphore等,用于控制进程之间的访问。此外,也可以使用Python中的Queue模块实现进程之间的通信。
代码示例:
import multiprocessing def worker(num): """任务函数""" print('Worker %d is running' % num) return num**2 if __name__ == '__main__': # 创建进程池对象 pool = multiprocessing.Pool(processes=4) # 任务参数列表 nums = [1, 2, 3, 4, 5] # 执行任务并获取结果 results = pool.map(worker, nums) print(results)
python多进程与多线程的结合
每个进程用多个线程执行,这样可以在每个进程内部实现并行处理IO任务,同时也可以充分利用多核处理器的优势。
代码示例:
import multiprocessing import threading def worker(num): """线程函数,用于处理任务""" print(f"Worker {num} is running...") def main(): """主函数,创建多个进程和线程""" # 创建3个进程 processes = [] for i in range(3): p = multiprocessing.Process(target=process_worker, args=(i,)) processes.append(p) p.start() # 在每个进程内部创建2个线程 for p in processes: for i in range(2): t = threading.Thread(target=worker, args=(i,)) t.start() if __name__ == '__main__': main()
这篇关于Python多线程与GIL锁的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门
- 2024-11-14Python编程入门指南
- 2024-11-13Python基础教程
- 2024-11-12Python编程基础指南
- 2024-11-12Python基础编程教程
- 2024-11-08Python编程基础与实践示例
- 2024-11-07Python编程基础指南
- 2024-11-06Python编程基础入门指南
- 2024-11-06怎么使用python 计算两个GPS的距离功能-icode9专业技术文章分享