使用线程创建类实例数组报错及线程同步必要性咨询
问题根源
你遇到的AttributeError是因为**aDataList里存储的是Thread对象,而非AData类的实例**。线程执行simulate_punction生成的初始化参数没有被用来创建AData实例,也没有存入列表,导致调用get_at()时找不到对应方法。
解决方案
要实现多线程生成AData实例并安全存入列表,需要解决两个核心问题:
- 让线程执行完后将生成的
AData实例存入容器 - 保证多线程对容器的操作线程安全
以下提供两种可行实现:
方法1:使用线程安全的queue.Queue
queue.Queue是Python内置的线程安全容器,无需手动加锁:
from threading import Thread from queue import Queue from aData import AData class SW: def __init__(self): self.aDataList = [] self.result_queue = Queue() threads = [] # 创建并启动线程 for _ in range(360): th = Thread(target=self._generate_adata, args=(150, 0.01)) threads.append(th) th.start() # 等待所有线程完成 for thread in threads: thread.join() # 从队列取出所有AData实例 while not self.result_queue.empty(): self.aDataList.append(self.result_queue.get()) # 测试调用 print(self.aDataList[0].get_at()) def _generate_adata(self, p, g): # 调用类方法生成参数,创建AData实例 at, fr, es = AData.simulate_punction(p, g) adata = AData(at, fr, es) # 将实例存入线程安全队列 self.result_queue.put(adata) # 实例化SW类执行 if __name__ == "__main__": sw = SW()
方法2:使用threading.Lock保护普通列表
如果想用普通列表,需要用锁来同步多线程的append操作,避免竞态条件:
from threading import Thread, Lock from aData import AData class SW: def __init__(self): self.aDataList = [] self.lock = Lock() threads = [] for _ in range(360): th = Thread(target=self._generate_adata, args=(150, 0.01)) threads.append(th) th.start() for thread in threads: thread.join() print(self.aDataList[0].get_at()) def _generate_adata(self, p, g): at, fr, es = AData.simulate_punction(p, g) adata = AData(at, fr, es) # 获取锁后再修改列表 with self.lock: self.aDataList.append(adata) if __name__ == "__main__": sw = SW()
关于线程同步的问题
需要同步。虽然CPython中列表的append操作是原子性的,但这是CPython的实现细节,并非Python语言规范。如果后续代码涉及列表的其他修改操作(如插入、删除),或者需要保证跨平台/解释器的一致性,必须通过锁或线程安全容器来同步访问,避免数据竞争导致的异常。
内容的提问来源于stack exchange,提问作者Rachel
相关产品推荐
相关产品推荐

