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

Multiple threads adding values in a unordered_map at the same time makes it crash

本文关键字:添加 崩溃 map 线程 unordered      更新时间:2023-10-16
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 毫秒是我假设它已经存储了变量值的时间,但是如果在速度较慢的计算机上需要更长的时间怎么办?这不是正确的方法。

我该如何解决这个问题?

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

提前谢谢。

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

没有如果,但是或为什么。

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

经过这么多票的下降,我实际上开始寻找互斥,人们在这里谈论,过了一会儿我发现它真的很容易使用。 正如我在这里的同伴告诉我的那样,这是正确的方法。谢谢大家的帮助=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.

它工作得很好,谢谢大家的帮助和批评。 哈哈

我通过预定义我想使用它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)
            }