多线程环境下共享类属性后无法正确打印数值的解决方法
多线程跨模块共享类实例属性时读取始终为0的问题解决
问题场景
开发了一个按日、按小时统计操作次数的程序,用Data类的daily和hourly实例存储统计值。后台通过多线程运行background函数实现控制台菜单,用来查看、打印或修改变量,但每次从线程中打印类属性时都显示0,而主线程中直接打印能得到正确的更新后的值。
代码复现
module a
class Data(): def __init__(self, some_count): self.some_count = some_count daily = Data(0) hourly = Data(0)
module b
from a import daily, hourly def print_data(command): if command == "daily": print(f"Daily saying hi is: {daily.some_count}") if command == "hourly": print(f"Hourly saying hi is: {hourly.some_count}") def background(): # 控制台菜单函数,支持打印类属性 while True: print_data(input()) # 输入命令选择要查看的统计值
module c
import threading import time from a import daily, hourly from b import background threading1 = threading.Thread(target=background) threading1.daemon = True threading1.start() # 主线程更新统计值,此处直接打印能得到正确值 while True: hourly.some_count += 1 daily.some_count += 2 time.sleep(10) # 简化示例,替换原代码的10000
注:以上为简化示意代码,非直接可运行版本
问题排查
最初怀疑是线程导致实例变异或导入机制问题,核心矛盾点在于:主线程中实例属性更新正常,但后台线程中读取的实例属性始终为初始值0,说明两个线程中访问的可能不是同一个实例,或者导入时的引用出现了隔离。
解决方案
将类声明与实例化操作拆分到独立模块,确保所有模块和线程引用同一个全局实例:
- 创建单独的模块(比如
class_declaration.py),仅存放Data类的声明:
class Data(): def __init__(self, some_count): self.some_count = some_count
- 在统一的实例化模块(比如
instance_store.py)中创建全局实例:
from class_declaration import Data daily = Data(0) hourly = Data(0)
- 所有需要使用实例的模块(module b、module c)统一从
instance_store.py导入实例:
# module b 修改后 from instance_store import daily, hourly # ... 其余代码不变 # module c 修改后 from instance_store import daily, hourly # ... 其余代码不变
通过这种方式,实现了跨模块与线程的变量共享,解决了属性读取始终为初始值的问题。
内容的提问来源于stack exchange,提问作者Tom02
相关产品推荐
相关产品推荐

