面试题答案
一键面试from functools import lru_cache
@lru_cache(maxsize=128)
def safe_get_value(dicts, target_key):
for d in dicts:
value = d.get(target_key)
if value is not None:
return value
return None
性能优化说明
- 缓存机制:使用
functools.lru_cache
装饰器实现缓存。它会自动缓存函数的输入和输出,当相同的dicts
和target_key
再次调用函数时,直接返回缓存的结果,避免重复查找,提高性能。maxsize
参数设置缓存的最大条目数,当缓存满了之后,最久未使用的条目会被移除。
多线程环境下的问题及解决方案
- 问题:
- 缓存一致性:在多线程环境下,不同线程可能同时调用该函数,由于
lru_cache
是基于函数输入输出进行缓存的,可能会出现缓存污染问题。例如,一个线程修改了dicts
中的某个字典,而其他线程从缓存中获取到了旧的结果。 - 线程安全:
lru_cache
本身并不是线程安全的,多个线程同时访问和修改缓存可能会导致数据竞争,引发未定义行为。
- 缓存一致性:在多线程环境下,不同线程可能同时调用该函数,由于
- 解决方案:
- 缓存一致性:尽量避免在多线程环境下修改
dicts
中的字典。如果必须修改,可以在修改后清除相关的缓存条目。lru_cache
提供了cache_clear
方法,可以在修改数据后调用safe_get_value.cache_clear()
来清除缓存。 - 线程安全:使用
threading.Lock
来保证线程安全。在函数调用前后加锁,确保同一时间只有一个线程能访问函数及缓存。
- 缓存一致性:尽量避免在多线程环境下修改
import threading
from functools import lru_cache
lock = threading.Lock()
@lru_cache(maxsize=128)
def safe_get_value(dicts, target_key):
with lock:
for d in dicts:
value = d.get(target_key)
if value is not None:
return value
return None
这样在多线程环境下,通过锁机制保证了函数调用及缓存访问的线程安全性。