python 字典的线程安全问题

2023-02-23 00:00:00 线程 字典 安全问题

Python 中的标准字典 dict 并不是线程安全的,因为它在并发写入时可能会导致数据竞争(data race)问题,从而导致程序出现错误或崩溃。

如果需要在多线程环境下安全地使用字典,可以考虑使用线程安全的字典实现,例如 collections.defaultdict 或 multiprocessing.Manager().dict()。

defaultdict 是 Python 标准库中的一个类,它与 dict 类似,但是可以在创建时指定默认值。如果使用 defaultdict 存储计数器,就可以避免在增加计数时出现 KeyError 错误。以下是一个示例代码:

import collections
import threading

counter = collections.defaultdict(int)
lock = threading.Lock()

def count(key):
    with lock:
        counter[key] += 1

threads = [threading.Thread(target=count, args=('a',)) for i in range(10)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

print(counter)  # 输出 defaultdict(<class 'int'>, {'a': 10})

在上述代码中,我们使用 defaultdict(int) 创建了一个默认值为 0 的计数器 counter,然后使用互斥锁 lock 来保证多线程安全。

另一种线程安全的字典实现是 multiprocessing.Manager().dict(),它是在 multiprocessing 模块中提供的。以下是一个示例代码:

import multiprocessing

def worker(d, key):
    with d.get_lock():
        d[key] += 1

manager = multiprocessing.Manager()
d = manager.dict()
processes = [multiprocessing.Process(target=worker, args=(d, 'a')) for i in range(10)]
for process in processes:
    process.start()
for process in processes:
    process.join()

print(d)  # 输出 {'a': 10}

在上述代码中,我们使用 multiprocessing.Manager() 创建了一个进程共享的字典 d,然后使用 d.get_lock() 获取锁来保证多进程安全。

相关文章