MST

星途 面试题库

面试题:Python多线程图书排名系统中线程安全问题

在实现Python多线程图书排名系统时,会涉及多个线程同时访问和修改图书排名数据。请举例说明可能出现的线程安全问题,并阐述如何使用Python中的锁机制来解决这些问题。
30.4万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

可能出现的线程安全问题示例

假设有一个简单的图书排名数据结构,用字典表示,键为图书ID,值为排名分数。例如:book_rank = {'book1': 10, 'book2': 5}

当多个线程同时对图书排名进行操作,比如增加某本图书的分数时,可能出现以下问题:

  1. 数据竞争
import threading

book_rank = {'book1': 10}

def increase_rank():
    rank = book_rank['book1']
    rank = rank + 1
    book_rank['book1'] = rank

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

for t in threads:
    t.join()

print(book_rank['book1'])

在这个例子中,多个线程同时读取book1的排名,然后各自增加1,再写回。由于线程执行顺序不确定,可能会导致最终结果小于预期的20(假设预期每个线程都成功增加1)。这是因为多个线程在读取和写入数据之间存在时间差,导致数据被覆盖,出现数据不一致。

使用锁机制解决问题

Python中的threading.Lock可以用来解决上述问题。

import threading

book_rank = {'book1': 10}
lock = threading.Lock()

def increase_rank():
    global book_rank
    lock.acquire()
    try:
        rank = book_rank['book1']
        rank = rank + 1
        book_rank['book1'] = rank
    finally:
        lock.release()

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

for t in threads:
    t.join()

print(book_rank['book1'])

在上述代码中,lock.acquire()获取锁,确保只有一个线程可以进入临界区(读取、修改和写入图书排名的代码段)。try - finally语句确保无论在临界区内发生什么,锁都会被释放(通过lock.release()),这样其他线程才有机会获取锁并操作数据,从而避免了数据竞争问题,保证了线程安全。