面试题答案
一键面试可能出现的问题
- 数据竞争:多个线程同时访问和修改共享列表时,由于线程执行顺序的不确定性,可能导致最终结果与预期不符。例如,一个线程读取列表中的某个值,在另一个线程修改该值后,第一个线程再进行计算,这就会产生错误的计算结果。
解决方案及代码实现
- 使用锁(
Lock
):
import threading
shared_list = []
lock = threading.Lock()
def modify_list():
global shared_list
with lock:
# 模拟修改操作
shared_list.append(1)
threads = []
for _ in range(10):
t = threading.Thread(target=modify_list)
threads.append(t)
t.start()
for t in threads:
t.join()
print(shared_list)
在上述代码中,通过lock
对象的上下文管理器(with
语句)来确保在任何时刻只有一个线程可以访问和修改共享列表shared_list
。进入with
块时自动获取锁,离开with
块时自动释放锁。
- 使用信号量(
Semaphore
):
import threading
shared_list = []
semaphore = threading.Semaphore(1)
def modify_list():
global shared_list
semaphore.acquire()
try:
# 模拟修改操作
shared_list.append(1)
finally:
semaphore.release()
threads = []
for _ in range(10):
t = threading.Thread(target=modify_list)
threads.append(t)
t.start()
for t in threads:
t.join()
print(shared_list)
这里使用Semaphore
,并将初始值设为1,作用与Lock
类似,都是保证同一时间只有一个线程能进入临界区修改共享列表。acquire
方法获取信号量,如果信号量的值为0则等待,release
方法释放信号量。在try - finally
块中确保无论修改操作是否成功,信号量都会被正确释放。