线程共享资源:Queue与Dictionary的选择及共享实现
线程间共享变量问题
我有两个包含while循环的线程,线程1处理的数据需由线程2并行处理,需要共享变量。
测试输入:
data = iter([1,2,3,4,5,6,7,8,9])
线程1实现代码:
import threading from queue import Queue import time class Thread1(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue _download = {} def run(self): i = 0 while True: _download[i] = next(data) self.queue.put(next(data)) time.sleep(1) i += 1
线程2实现代码:
class Thread2(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue def run(self): while True: self.queue.get() time.sleep(3)
主函数代码:
q = Queue(maxsize=10) t = Thread1(q) s = Thread2(q) t.start() s.start()
目前线程2可通过Queue访问共享变量,但我还想让线程2访问线程1中的_download字典。现提出两个问题:
- 如何实现线程2对该字典的访问?
- 应该选择Queue还是Dictionary来实现线程间的资源共享?
问题1:实现线程2对_download字典的访问
首先要修正线程1的代码:你当前的_download是局部变量,无法被外部访问,需要改成线程1的实例属性(即self._download = {})。之后有两种可行实现方式:
方式1:给线程2传入线程1实例
修改线程2的初始化逻辑,让它持有线程1的引用,直接访问其字典属性:
class Thread2(threading.Thread): def __init__(self, queue, thread1): threading.Thread.__init__(self) self.queue = queue self.thread1 = thread1 # 保存线程1实例 def run(self): while True: self.queue.get() # 直接访问线程1的_download字典 print(self.thread1._download) time.sleep(3)
主函数对应修改:
q = Queue(maxsize=10) t = Thread1(q) s = Thread2(q, t) # 传入线程1实例 t.start() s.start()
方式2:使用独立的共享字典对象
提前创建字典,初始化线程1和线程2时都传入这个字典实例,让两者共享:
# 提前创建共享字典和线程锁 lock = threading.Lock() shared_download = {} class Thread1(threading.Thread): def __init__(self, queue, download_dict): threading.Thread.__init__(self) self.queue = queue self.download_dict = download_dict def run(self): i = 0 while True: try: val = next(data) # 写字典时加锁保证线程安全 with lock: self.download_dict[i] = val self.queue.put(next(data)) time.sleep(1) i += 1 except StopIteration: break # 处理迭代器耗尽,避免死循环 class Thread2(threading.Thread): def __init__(self, queue, download_dict): threading.Thread.__init__(self) self.queue = queue self.download_dict = download_dict def run(self): while True: try: self.queue.get() # 读字典时加锁保证线程安全 with lock: print(self.download_dict) time.sleep(3) self.queue.task_done() except: break
主函数对应修改:
q = Queue(maxsize=10) t = Thread1(q, shared_download) s = Thread2(q, shared_download) t.start() s.start() t.join() s.join()
⚠️ 关键提醒:Python普通字典不是线程安全的,多线程同时读写必须加锁,否则会出现数据错乱或程序崩溃。
问题2:选择Queue还是Dictionary实现线程间资源共享
两者适用场景不同,按需选择:
优先用Queue的场景
- 核心需求是生产者-消费者模式:Queue本身是线程安全的,内置锁机制,无需手动处理锁逻辑,避免bug。
- 数据单向流动:线程1生产、线程2顺序消费的场景,Queue天然适配,还能通过
maxsize限制队列长度,防止内存溢出。 - 不需要随机访问数据:Queue是先进先出结构,适合按顺序处理数据的场景。
用Dictionary的场景
- 需要随机访问共享数据:比如线程2要根据键值直接获取特定数据,而非顺序处理。
- 需要维护共享状态:比如需要保存线程1处理的所有数据状态,但必须配合线程锁使用,保证线程安全。
总结
如果你的核心需求是让线程2并行处理线程1生产的数据,优先选Queue,它更贴合场景且线程安全。如果需要额外访问线程1的状态数据,可以结合共享字典+锁的方式,但务必做好线程安全保护。
内容的提问来源于stack exchange,提问作者bugrahaskan
相关产品推荐
相关产品推荐

