Can I access a C++11 std::map entry while inserting/erasing from another thread?

前端 未结 4 1085
半阙折子戏
半阙折子戏 2021-01-12 15:16

Can I access (without locking) an std::map entry while another thread inserts/erases entrys?

example pseudo C++:

typedef struct {
   int value;
   in         


        
4条回答
  •  爱一瞬间的悲伤
    2021-01-12 15:50

    No no no no no!

    map::erase modifies the links between the map entries and that messes with the search algorithm used in map::at. You can use the elements during an erase, but you can not execute the searching algorithm itself!

    I've created an illustration program. On my machine this program sometimes print OK, sometimes throws a map exception - that means that the search is gone wrong. Increasing the number of reading threads make the exception appear more often.

    #include 
    #include 
    #include 
    #include 
    
    std::map m;
    
    // this thread uses map::at to access elements
    void foo()
    {
      for (int i = 0; i < 1000000; ++i) {
        int lindex = 10000 + i % 1000;
        int l = m.at(lindex);
        assert(l == lindex);
        int hindex = 90000 + i % 1000;
        int h = m.at(hindex);
        assert(h == hindex);
      }
      std::cout << "OK" << std::endl;
    }
    
    // this thread uses map::erase to delete elements
    void bar()
    {
      for (int i = 20000; i < 80000; ++i) {
        m.erase(i);
      }
    }
    
    int main()
    {
      for (int i = 0; i < 100000; ++i) {
        m[i] = i;
      }
    
      std::thread read1(foo);
      std::thread read2(foo);
      std::thread erase(bar);
    
      read1.join();
      read2.join();
      erase.join();
    
      return 0;
    }
    

提交回复
热议问题