面试题答案
一键面试面临的挑战
- 数据一致性问题:多线程同时读取和修改字典,可能导致读取到不一致的数据。例如,一个线程正在修改字典结构(如添加或删除键值对),另一个线程同时读取,可能获取到部分修改后、部分修改前的数据。
- 竞态条件:多个线程同时尝试修改字典,可能导致最终结果取决于线程执行的顺序,出现不可预测的行为。比如两个线程同时尝试增加同一个键的值,如果没有适当的同步机制,可能只增加了一次,而不是两次。
保证不可变性与多线程安全的方法
- 使用
collections.abc.Mapping
抽象基类创建不可变字典:通过继承collections.abc.Mapping
并只实现__getitem__
、__len__
和__iter__
方法,可创建不可变字典。 - 使用锁机制:在多线程环境中,使用
threading.Lock
来同步对字典的访问,确保同一时间只有一个线程能操作字典。
关键代码片段
import threading
from collections.abc import Mapping
class ImmutableDict(Mapping):
def __init__(self, data):
self._data = data.copy()
self._lock = threading.Lock()
def __getitem__(self, key):
with self._lock:
return self._data[key]
def __len__(self):
with self._lock:
return len(self._data)
def __iter__(self):
with self._lock:
return iter(self._data)
# 示例使用
my_dict = ImmutableDict({'a': 1, 'b': 2})
def read_dict():
print(my_dict['a'])
threads = []
for _ in range(5):
t = threading.Thread(target=read_dict)
threads.append(t)
t.start()
for t in threads:
t.join()
在上述代码中,ImmutableDict
类继承自collections.abc.Mapping
,实现了不可变字典的基本行为。_lock
用于线程同步,在访问字典数据的方法中使用with self._lock
确保线程安全。