首页 > 开发 > C++ > 正文

不同线程访问同一个类对象导致成员数据异常的问题

2017-09-11 21:19:28  来源: 网友分享

有两个类

class TestClass
{

public:    TestClass();    map<int,int> int_map;

};
class TestClass2
{

public:    TestClass2(TestClass* tc);    void Run();    TestClass* tc1;

};

TestClass::TestClass()
{

printf("TestClass1 addr :%p \n",this);

}
TestClass2::TestClass2(TestClass* tc){

tc1 = tc;printf("TestClass2 get TestClass1 ,addr :%p !\n",tc1);

}
void TestClass2::Run(){

    int i = 0;    while(true){    tc1->int_map.insert(make_pair(i,1));    printf("TestClass2:size of TestClass1 %p 's int_map is %d!\n",tc1,tc1->int_map.size());    sleep(2);    i++;}

}

int main()
{

TestClass* tc1 = new TestClass();printf("tc1 addr is %p!\n",tc1);TestClass2* tc2 = new TestClass2(tc1);pid_t pid = fork();if(pid == 0){    while(1){        sleep(1);        printf("TestClass1 :%p int_map size %d!\n",tc1,tc1->int_map.size());    }}else{    tc2->Run();}

}
TestClass2 初始化后获得TestClass对象的指针,
通过这个指针来访问TestClass中的map,
每次访问后打印size

两个类在不同的线程打印,按理说size应该一样,
结果TestClass2可以输出数量,而TestClass自己本身却输出0

解决方案

  1. 如果你的本意是验证多线程情况下对共享资源的访问,那你代码实现有误,fork()是派生一个子进程和线程没啥关系,而子进程拷贝了一份父进程环境变量和对象信息,已经和父进程的没啥关系了;u3000c++11提供了线程库,直接取用
  2. 修改了一下你的代码(完整见这里),实际上是可以观测到共享数据的修改的.
     TestClass* tc1 = new TestClass();     printf("tc1 addr is %p!\n",tc1);     TestClass2* tc2 = new TestClass2(tc1);      std::thread t([&](){tc2->Run();});     t.detach();      do {         std::this_thread::sleep_for(1s);         cout<<"TestClass1:size of TestClass1 tc1->int_map size:"<<tc1->int_map.size()<<std::endl;     } while(true);

结果如下:

tc1 addr is 0x1ee1c20!
TestClass2 get TestClass1, addr0x1ee1c20
TestClass2:size of TestClass1 tc1->int_map size:1
TestClass1:size of TestClass1 tc1->int_map size:1
TestClass2:size of TestClass1 tc1->int_map size:2
TestClass1:size of TestClass1 tc1->int_map size:2
TestClass1:size of TestClass1 tc1->int_map size:2
TestClass2:size of TestClass1 tc1->int_map size:3
TestClass1:size of TestClass1 tc1->int_map size:3
TestClass1:size of TestClass1 tc1->int_map size:3