Python线程中变量重新赋值无法同步至主线程的技术咨询
嘿,这俩问题其实都是同一个坑——Python的对象引用和参数传递逻辑在搞事情!咱们一个个拆解清楚:
问题1:重新赋值列表后主线程看不到变化的原因
你把stocksOnScreenListInfo传给线程函数时,线程里的这个变量只是原列表对象的一个"别名"(引用)。用append的时候,你是直接在原列表对象上修改内容,所以主线程里的引用指向的还是同一个列表,自然能看到更新。
但一旦执行stocksOnScreenListInfo = placeholder,你就给线程里的局部变量换了个新对象——它现在指向placeholder这个新列表了,而主线程里的stocksOnScreenListInfo还死死盯着原来的空列表,当然看不到变化啦!
问题2:stocksOnScreen无法同步更新的原因
和上面一模一样!stocksOnScreen一开始指向["AAPL"]这个列表对象,线程里的stocksOnScreen = UpdateScreen(...)只是让线程内的变量指向了新的["TSLA"]列表,主线程里的变量根本没动,还是指向最初的那个列表。
解决方案:别换对象,改对象内容,或者用共享容器
针对问题1的快速修复
不用重新赋值列表,而是清空原列表再把新内容加进去,直接修改原对象:
def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen): while(True): placeholder = [] for stock in stocksOnScreen: placeholder.append(RetrieveQuote(stock)) # 清空原列表,再添加新内容 stocksOnScreenListInfo.clear() stocksOnScreenListInfo.extend(placeholder) time.sleep(5)
针对问题2的通用解决方案(适合所有共享变量场景)
因为stocksOnScreen是要被完全替换的,用可变容器封装会更优雅,比如字典或者自定义类:
方法1:用字典封装共享变量
def main(args): # 用字典装所有需要共享的变量 shared_data = { "stocksOnScreen": ["AAPL"], "stocksOnScreenListInfo": [] } thread_data_collector = threading.Thread(target=dataCollector_thread, args=(shared_data,)) thread_data_collector.daemon = True thread_data_collector.start() thread_screen = threading.Thread(target=screenUpdate_thread, args=(stocksSearchArray, shared_data)) thread_screen.daemon = True thread_screen.start() def dataCollector_thread(shared_data): while(True): placeholder = [] for stock in shared_data["stocksOnScreen"]: placeholder.append(RetrieveQuote(stock)) shared_data["stocksOnScreenListInfo"].clear() shared_data["stocksOnScreenListInfo"].extend(placeholder) time.sleep(5) def screenUpdate_thread(stocksSearchArray, shared_data): while(True): # 直接修改字典里的值,原对象不变 shared_data["stocksOnScreen"] = UpdateScreen(stocksSearchArray) time.sleep(1) # 加个sleep避免线程无限循环占CPU
方法2:自定义共享数据类(代码更清晰)
from threading import Lock class SharedData: def __init__(self): self.stocksOnScreen = ["AAPL"] self.stocksOnScreenListInfo = [] self.lock = Lock() # 提前加锁,避免并发读写问题 def main(args): shared_data = SharedData() thread_data_collector = threading.Thread(target=dataCollector_thread, args=(shared_data,)) thread_data_collector.daemon = True thread_data_collector.start() thread_screen = threading.Thread(target=screenUpdate_thread, args=(stocksSearchArray, shared_data)) thread_screen.daemon = True thread_screen.start() def dataCollector_thread(shared_data): while(True): placeholder = [] # 读取共享变量时加锁,避免被中途修改 with shared_data.lock: stocks = shared_data.stocksOnScreen.copy() for stock in stocks: placeholder.append(RetrieveQuote(stock)) with shared_data.lock: shared_data.stocksOnScreenListInfo.clear() shared_data.stocksOnScreenListInfo.extend(placeholder) time.sleep(5) def screenUpdate_thread(stocksSearchArray, shared_data): while(True): new_stocks = UpdateScreen(stocksSearchArray) with shared_data.lock: shared_data.stocksOnScreen = new_stocks time.sleep(1)
额外提醒:线程安全很重要!
如果多个线程同时读写共享变量,比如dataCollector_thread在遍历stocksOnScreen时,screenUpdate_thread刚好修改了它,可能会出现异常或数据错乱。上面的代码里已经用Lock加了线程锁,确保同一时间只有一个线程能操作共享变量。
内容的提问来源于stack exchange,提问作者Jane Doe
相关产品推荐
相关产品推荐

