面试题答案
一键面试设计思路
为了保证复杂数据结构(如嵌套字典)在多线程读写操作下的数据完整性和线程安全,我们可以使用Python的threading
模块中的锁机制。这里的核心思想是,对于整个嵌套字典的操作,使用一个全局锁来保护,确保同一时间只有一个线程能够对数据结构进行修改。读操作时,由于不会改变数据,在无写操作的情况下可以允许多个线程同时进行,因此我们可以使用RLock
(可重入锁)来实现读写锁的功能,以提高读操作的并发性能。
锁的类型及原因
RLock
(可重入锁):- 原因:它允许同一个线程多次获取锁,而不会造成死锁。在复杂数据结构的操作中,可能会出现递归调用或者一个线程多次需要获取锁的情况,
RLock
能很好地处理这种场景。同时,它可以作为读写锁的基础,读操作时多个线程可以共享锁(只要没有写操作),写操作时则独占锁,从而保证数据的一致性。
- 原因:它允许同一个线程多次获取锁,而不会造成死锁。在复杂数据结构的操作中,可能会出现递归调用或者一个线程多次需要获取锁的情况,
代码实现
import threading
class ThreadSafeNestedDict:
def __init__(self):
self.data = {}
self.lock = threading.RLock()
def read(self, key1, key2=None):
with self.lock:
if key2 is None:
return self.data.get(key1)
else:
return self.data.get(key1, {}).get(key2)
def write(self, key1, value, key2=None):
with self.lock:
if key2 is None:
self.data[key1] = value
else:
if key1 not in self.data:
self.data[key1] = {}
self.data[key1][key2] = value
使用示例
def read_thread(tsnd, key1, key2=None):
value = tsnd.read(key1, key2)
print(f"Read value: {value}")
def write_thread(tsnd, key1, value, key2=None):
tsnd.write(key1, value, key2)
print(f"Wrote value: {value}")
if __name__ == "__main__":
tsnd = ThreadSafeNestedDict()
threads = []
threads.append(threading.Thread(target=write_thread, args=(tsnd, 'key1','subkey1', [1, 2, 3])))
threads.append(threading.Thread(target=read_thread, args=(tsnd, 'key1','subkey1')))
threads.append(threading.Thread(target=write_thread, args=(tsnd, 'key2','subkey3', 42)))
threads.append(threading.Thread(target=read_thread, args=(tsnd, 'key2','subkey3')))
for thread in threads:
thread.start()
for thread in threads:
thread.join()
在上述代码中,ThreadSafeNestedDict
类封装了嵌套字典,并使用RLock
来保护对字典的读写操作。read
方法用于读取数据,write
方法用于写入数据,每个方法在操作数据前都会获取锁,操作完成后释放锁,从而保证数据的线程安全性。