线程内SentMessage函数无法读取更新后的p1值,求解决方法
问题解决思路
核心问题分析
你遇到的问题本质有两个:
- 参数传递方式错误:
windowa.WindowOpen(p1, p2)如果是按值传递,函数内部修改的只是p1的副本,原全局变量p1的positionX根本没被更新,线程自然一直读初始值100。 - 多线程内存可见性问题:即便改成传引用,多线程环境下CPU可能会把变量缓存到寄存器,线程读取的是旧的缓存值,看不到其他线程的修改。
具体解决方案
1. 修正参数传递为引用
修改WindowOpen的函数签名,把参数改成引用传递,这样函数内部对p1的修改会直接作用到原对象:
// 假设WindowOpen的定义原本是传值,现在改成引用 void WindowOpen(Hero& p1, Hero& p2) { // 这里的修改会直接影响外部的p1变量 p1.positionX += 1; // 示例修改逻辑 }
2. 保证多线程内存可见性
有两种常用方式解决这个问题:
方式一:用volatile修饰变量
在Hero结构体中,把positionX声明为volatile,告诉编译器这个变量会被多线程修改,不要做缓存优化,每次读取都从内存获取最新值:
struct Hero { string imgPath; volatile int positionX; // 加volatile修饰 int positionY; int speed; };
方式二:用互斥锁同步读写(更安全)
如果positionX的修改是复合操作(比如positionX += 5),或者需要避免读写冲突,用互斥锁更稳妥,同时也能保证内存可见性:
#include <mutex> #include <thread> #include <chrono> std::mutex mtx; // 全局互斥锁 void SentMessage() { while (true) { std::lock_guard<std::mutex> lock(mtx); // 读取前加锁 std::cout << p1.positionX << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 加延迟减少CPU占用 } } void WindowOpen(Hero& p1, Hero& p2) { while (true) { std::lock_guard<std::mutex> lock(mtx); // 修改前加锁 p1.positionX += 1; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }
额外注意
死循环while(true)会占用大量CPU资源,建议在循环内加入短暂延迟(比如上面的sleep_for),避免系统资源浪费。
内容的提问来源于stack exchange,提问作者Fuji
相关产品推荐
相关产品推荐

