MST
星途 面试题库

面试题:Python Thread类与GIL及多核心利用

由于Python存在全局解释器锁(GIL),在多线程编程中,CPU密集型任务并不能充分利用多核CPU的优势。请结合Thread类,阐述如何在Python中通过一定的策略(如多进程与多线程结合等)在多核CPU环境下高效执行CPU密集型和I/O密集型混合的任务,并给出详细的设计思路和关键代码片段。
11.2万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. CPU密集型任务:使用multiprocessing模块创建进程,因为进程间相互独立,每个进程有自己的Python解释器实例,不存在GIL限制,能充分利用多核CPU。
  2. I/O密集型任务:使用threading模块创建线程,由于I/O操作时线程会释放GIL,线程在I/O等待时其他线程可执行,适合I/O密集型场景。
  3. 任务分配:分析任务类型,将CPU密集型任务交给进程池处理,I/O密集型任务交给线程池处理。

关键代码片段

import multiprocessing
import threading
import time


# CPU密集型任务
def cpu_bound_task(num):
    result = 0
    for i in range(10000000):
        result += i * num
    return result


# I/O密集型任务
def io_bound_task():
    time.sleep(2)
    return "I/O task completed"


if __name__ == '__main__':
    # 进程池处理CPU密集型任务
    cpu_pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
    cpu_results = []
    for i in range(4):
        cpu_result = cpu_pool.apply_async(cpu_bound_task, args=(i,))
        cpu_results.append(cpu_result)
    cpu_pool.close()
    cpu_pool.join()
    cpu_output = [result.get() for result in cpu_results]
    print("CPU bound task results:", cpu_output)

    # 线程池处理I/O密集型任务
    io_threads = []
    io_results = []
    for i in range(4):
        io_thread = threading.Thread(target=io_bound_task)
        io_threads.append(io_thread)
        io_thread.start()
    for thread in io_threads:
        thread.join()
        io_results.append("I/O task completed")
    print("I/O bound task results:", io_results)

解释

  1. cpu_bound_task函数:模拟CPU密集型任务,进行大量计算。
  2. io_bound_task函数:模拟I/O密集型任务,使用time.sleep模拟I/O等待。
  3. 进程池部分:创建进程池,通过apply_async异步提交CPU密集型任务,最后获取结果。
  4. 线程部分:创建线程并启动执行I/O密集型任务,最后收集结果。注意在if __name__ == '__main__':中执行是因为multiprocessing在Windows系统上的要求。