MST

星途 面试题库

面试题:Python多线程在Web开发中的资源竞争问题

在Python的Web开发中使用多线程时,常常会遇到资源竞争的情况。请举例说明可能出现资源竞争的场景,并阐述如何使用锁机制(如`threading.Lock`)来解决这个问题。
12.6万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

可能出现资源竞争的场景

假设我们有一个简单的Web应用,用于统计网站的访问次数。在多线程环境下,多个线程可能同时尝试增加这个访问次数的计数器。例如:

import threading

counter = 0


def increment():
    global counter
    for _ in range(100000):
        counter = counter + 1


threads = []
for _ in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print(f"Final counter value: {counter}")

在上述代码中,如果多个线程同时执行counter = counter + 1这行代码,由于这不是一个原子操作(实际上分为读取counter值、增加1、再写回counter值三个步骤),就可能出现资源竞争。比如线程A读取了counter的值为10,线程B也读取了counter的值为10,然后它们都增加1并写回,这样就丢失了一次增加操作,最终结果会小于预期的1000000(10个线程,每个线程增加100000次)。

使用锁机制解决问题

可以使用threading.Lock来解决这个问题。修改后的代码如下:

import threading

counter = 0
lock = threading.Lock()


def increment():
    global counter
    for _ in range(100000):
        with lock:
            counter = counter + 1


threads = []
for _ in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print(f"Final counter value: {counter}")

在上述代码中,with lock:语句创建了一个上下文管理器,当进入这个上下文时,锁被获取,当离开上下文时,锁被释放。这样,在任何时刻只有一个线程能够执行counter = counter + 1这行代码,从而避免了资源竞争,确保最终的counter值是准确的1000000。