多个线程同时在unordered_map中添加值会使其崩溃

时间:2012-04-07 18:33:10

标签: c++ multithreading visual-c++ c++-cli backgroundworker

unordered_map<std::string,unordered_map<std::string, std::string> >* storing_vars;

我在范围内声明的范围内有这个变量。

这是在构造函数中声明的。

this->storing_vars =  new unordered_map<std::string,unordered_map<std::string, std::string> >();

为了初始化它。

然后我做的是通过我的BackgroundWorker一遍又一遍地调用一个函数

for(int i2 = 0; i2 < 30; i2++){



                int index_pos_curr = i2;


                //Start the Threads HERE


                this->backgroundWorker2 = gcnew System::ComponentModel::BackgroundWorker;
                this->backgroundWorker2->WorkerReportsProgress = true;
                this->backgroundWorker2->WorkerSupportsCancellation = true;


                //this->backgroundWorker2->FieldSetter(L"std::string",L"test","damnnit");

                backgroundWorker2->DoWork += gcnew DoWorkEventHandler( this, &MainFacebook::backgroundWorker2_DoWork );
                backgroundWorker2->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &MainFacebook::backgroundWorker2_RunWorkerCompleted );
                backgroundWorker2->ProgressChanged += gcnew ProgressChangedEventHandler( this, &MainFacebook::backgroundWorker2_ProgressChanged );
                backgroundWorker2->RunWorkerAsync(index_pos_curr);
                Sleep(50); //THE PROBLEM IS HERE, IF I COMMENT THIS OUT it won't work, that's probably because there are a lot of functions trying to add values in the same variable (even though the indexes are differents in each call)
            }

完成此操作后,它将调用DoWork函数

void backgroundWorker2_DoWork(Object^ sender, DoWorkEventArgs^ e ){
             BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);         
             e->Result = SendThem( safe_cast<Int32>(e->Argument), worker, e );          

        }

int SendThem(int index){

            stringstream st;
            st << index;

            //...
            (*this->storing_vars)[st.str()]["index"] =  "testing1";
            (*this->storing_vars)[st.str()]["rs"] = "testing2";
            return 0;
}

当我在Sleep(50)行中添加注释时,我认为问题在于,由于后台的线程调用相同的函数,因此在调用很多次数据时存储数据存在问题甚至没有等待其他存储完成,它导致“xhash.h”文件中的错误,使用Sleep(50)清除了一个错误,但我不能使用它们,因为它冻结了我的UI,也50毫秒是我假设它已经存储了变量值的时间,但是如果它在较慢的计算机中需要更长的时间呢?这不是正确的方法。

我该如何解决这个问题?

我希望能够在不使用SLEEP的情况下更新unordered_map

提前致谢。

3 个答案:

答案 0 :(得分:3)

您一次只能从一个线程修改标准库容器(包括但不限于unordered_map)。解决方案是使用关键部分,互斥锁,锁来同步访问。如果您不知道这些是什么,那么您需要在之前了解,然后尝试创建多个线程。

没有ifs,buts或者为什么。

如果您有多个线程,则需要使用机制来同步它们,以序列化对共享数据的访问。常见的同步机制是上面提到的,所以去查找它们。

答案 1 :(得分:2)

经过如此多的投票,我实际上开始寻找Mutex,人们在这里谈论,过了一段时间我发现它真的很简单。这是我的同伴告诉我的正确方法。谢谢大家的帮助= D

这是我做的,我只需要添加

//Declare the Mutex
static Mutex^ mut = gcnew Mutex;

//then inside the function called over and over again I used mutex
mut->WaitOne();
//Declare/Update the variables
mut->ReleaseMutex();
//Then I release it.

它完美无缺,谢谢大家的帮助和批评。哈哈

答案 2 :(得分:-4)

我通过预定义unordered_map的索引找到了一个解决方案我想使用它,问题只是创建索引,多线程的更新似乎没问题。

for(int i2 = 0; i2 < 30; i2++){



                int index_pos_curr = i2;


                //Start the Threads HERE


                this->backgroundWorker2 = gcnew System::ComponentModel::BackgroundWorker;
                this->backgroundWorker2->WorkerReportsProgress = true;
                this->backgroundWorker2->WorkerSupportsCancellation = true;
                backgroundWorker2->DoWork += gcnew DoWorkEventHandler( this, &MainFacebook::backgroundWorker2_DoWork );
                backgroundWorker2->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &MainFacebook::backgroundWorker2_RunWorkerCompleted ); stringstream st; st << index_pos_curr;

                (*this->storing_vars)[st.str()]["index"] = ""; 
               //This ^^^^^ will initialize it and then in the BackgroundWorker will only update, this way it doesn't crash. :)

                backgroundWorker2->ProgressChanged += gcnew ProgressChangedEventHandler( this, &MainFacebook::backgroundWorker2_ProgressChanged );
                backgroundWorker2->RunWorkerAsync(index_pos_curr);
                Sleep(50); //THE PROBLEM IS HERE, IF I COMMENT THIS OUT it won't work, that's probably because there are a lot of functions trying to add values in the same variable (even though the indexes are differents in each call)
            }