MST

星途 面试题库

面试题:Python类实例化与多线程环境下的资源竞争问题

在多线程环境中,Python类的实例化可能会面临资源竞争问题。假设你正在开发一个多线程应用,其中某个类的实例化涉及共享资源的访问,描述可能出现的资源竞争场景,并给出解决方案,要求从底层原理(如GIL、锁机制等)进行分析,同时提供代码示例。
19.8万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

可能出现的资源竞争场景

在Python多线程环境中,当多个线程同时实例化涉及共享资源访问的类时,可能出现资源竞争。例如,类的初始化方法中对一个共享的计数器变量进行递增操作。如果没有适当的同步机制,可能会出现一个线程读取了计数器的值,还没来得及更新,另一个线程也读取了相同的值,导致更新丢失,最终计数器的值并非预期的正确结果。

底层原理分析

  1. GIL(全局解释器锁):Python的多线程在CPython解释器中由于GIL的存在,同一时刻只有一个线程能执行Python字节码。这意味着在CPU密集型任务中,多线程并不能真正利用多核优势。但在I/O密集型任务中,线程在等待I/O操作时会释放GIL,其他线程可以趁机执行。然而,对于共享资源的访问,GIL并不能完全解决竞争问题,因为在访问共享资源的代码段内,GIL依然可能导致不同线程在不同时间点访问共享资源,出现数据不一致。
  2. 锁机制:为了解决资源竞争问题,可以使用锁机制。锁有多种类型,如互斥锁(threading.Lock)。当一个线程获取到锁,其他线程就必须等待锁被释放才能获取锁并执行相关代码,从而保证同一时间只有一个线程能访问共享资源。

解决方案及代码示例

使用互斥锁来同步对共享资源的访问。

import threading

# 共享资源
counter = 0
lock = threading.Lock()


class MyClass:
    def __init__(self):
        global counter
        with lock:
            # 模拟对共享资源的访问
            counter += 1
            print(f"实例化MyClass,当前计数器值: {counter}")


def create_instance():
    instance = MyClass()


# 创建多个线程实例化MyClass
threads = []
for _ in range(5):
    thread = threading.Thread(target=create_instance)
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

在上述代码中,通过with lock语句,确保了在对共享资源counter进行操作时,同一时间只有一个线程能进入该代码块,从而避免了资源竞争问题。