MST
星途 面试题库

面试题:Python线程锁在复杂数据结构同步中的应用

给定一个复杂的数据结构,如嵌套字典(例如 {'key1': {'subkey1': [1, 2, 3],'subkey2': 'value2'}, 'key2': {'subkey3': 42}}),多个线程需要同时对这个数据结构的不同部分进行读写操作。请设计并实现一个使用Python锁机制的方案,保证数据的完整性和线程安全,详细说明设计思路以及所使用锁的类型和原因。
34.2万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

设计思路

为了保证复杂数据结构(如嵌套字典)在多线程读写操作下的数据完整性和线程安全,我们可以使用Python的threading模块中的锁机制。这里的核心思想是,对于整个嵌套字典的操作,使用一个全局锁来保护,确保同一时间只有一个线程能够对数据结构进行修改。读操作时,由于不会改变数据,在无写操作的情况下可以允许多个线程同时进行,因此我们可以使用RLock(可重入锁)来实现读写锁的功能,以提高读操作的并发性能。

锁的类型及原因

  1. 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方法用于写入数据,每个方法在操作数据前都会获取锁,操作完成后释放锁,从而保证数据的线程安全性。