面试题答案
一键面试可能出现的问题分析
在多线程环境下,多个线程同时对字典进行读取和写入操作时,可能会出现以下数据竞争问题:
- 数据不一致:比如一个线程正在读取字典中的某个配置值,而另一个线程同时对该值进行修改,这可能导致读取到的值是部分修改后的,造成数据不一致。
- 丢失更新:两个线程同时读取配置字典中的某个值,然后各自进行修改并写回,可能导致其中一个线程的修改被覆盖,造成丢失更新。
方案一:使用threading
模块中的锁机制
原理:通过在对配置字典进行访问和修改的代码段前后加锁,保证同一时间只有一个线程可以进入该代码段,从而避免数据竞争。
代码示例:
import threading
# 全局配置字典
config_dict = {}
# 创建锁对象
lock = threading.Lock()
def update_config(key, value):
global config_dict
with lock:
config_dict[key] = value
def get_config(key):
global config_dict
with lock:
return config_dict.get(key)
# 模拟多线程操作
def thread_task():
update_config('test_key', 'test_value')
print(get_config('test_key'))
threads = []
for _ in range(5):
t = threading.Thread(target=thread_task)
threads.append(t)
t.start()
for t in threads:
t.join()
方案二:使用multiprocessing.Manager
中的dict
原理:multiprocessing.Manager
提供了一种跨进程(同样适用于多线程场景)共享对象的方式。Manager.dict
创建的字典是线程安全的,内部实现了锁机制等同步手段,使得多线程访问时不会出现数据竞争问题。
代码示例:
import multiprocessing
import threading
def update_config(config_dict, key, value):
config_dict[key] = value
def get_config(config_dict, key):
return config_dict.get(key)
def thread_task(config_dict):
update_config(config_dict, 'test_key', 'test_value')
print(get_config(config_dict, 'test_key'))
if __name__ == '__main__':
manager = multiprocessing.Manager()
config_dict = manager.dict()
threads = []
for _ in range(5):
t = threading.Thread(target=thread_task, args=(config_dict,))
threads.append(t)
t.start()
for t in threads:
t.join()