为何C++线程调用实例成员函数时成员变量未共享?
C++线程间未共享类成员变量的问题分析
问题代码
// t.cpp #include <iostream> #include <thread> #include <chrono> class test { private: public: void fcn1(); void fcn2(); uint8_t i = 0; }; void test::fcn1() { while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(999)); std::cout << "hihi " << (float)i++ << std::endl; } } void test::fcn2() { std::cout << "yoyo " << (float)i++ << std::endl; } test t; std::thread tt(&test::fcn1, t); int main() { while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); t.fcn2(); } return 0; }
编译运行命令
g++ ./t.cpp -o t -lpthread; ./t
实际输出
hihi 0 yoyo 0 hihi 1 yoyo 1 hihi 2 yoyo 2 hihi 3 ...
预期输出
hihi 0 yoyo 1 hihi 2 yoyo 3 hihi 4 yoyo 5 ...
问题原因
核心错误是创建线程std::thread tt(&test::fcn1, t);时,第二个参数t是值传递,这会导致线程内部创建一个test类的副本,而非使用全局变量t本身。因此:
- 线程中的
fcn1操作的是副本的成员变量i - 主线程中的
fcn2操作的是全局变量t的成员变量i
两者完全是独立的实例,自然不会共享i的值,出现同步递增的现象。
修复方案
要让线程使用原实例,需要传递引用或指针:
- 使用
std::ref传递引用:
std::thread tt(&test::fcn1, std::ref(t));
- 传递指针:
std::thread tt(&test::fcn1, &t);
修改后,两个线程会操作同一个实例的i,就能得到预期的交替递增输出。另外注意,多线程操作共享变量时,需要考虑线程安全问题(比如加锁),避免竞态条件导致的未定义行为。
内容的提问来源于stack exchange,提问作者furynerd
相关产品推荐
相关产品推荐

