是std :: map :: end线程安全并且保证它对于同一个容器总是相同的吗?

Ale*_*lex 6 c++ concurrency multithreading c++11 c++14

我使用std::map并获得一个我可以使用的元素:http://www.cplusplus.com/reference/map/map/

还是:lower_bound()或者equal_range()- 和find()这种情况一样.

我不能用:

  • at() - 因为它抛出异常,我测量了10倍的性能下降
  • operator[] - 因为它插入一个元素(如果它不存在),这种行为是不可接受的

find() - 是我想要的.但我std::map在多线程程序中使用并通过锁保护它std::mutex.

还有std::map其他线程的插入和删除.

我应该保护std::map::end还是保证它对于一个分配的容器总是相同的?

我可以使用static auto const map_it_end = map1.end();不受保护的此类物品std::mutex吗?

http://ideone.com/tATn0H

#include <iostream>
#include <string>
#include <mutex>
#include <thread>
#include <map>

std::map<std::string, std::string> map1 ( {{"apple","red"},{"lemon","yellow"}} );
static auto const map_it_end = map1.end();
std::mutex mtx1;

void func() {
    std::lock_guard<std::mutex> lock1(mtx1);

    auto it1 = map1.find("apple");
    if(it1 != map_it_end)   // instead of: if(it1 != map1.end())
        std::cout << it1->second << ", ";
}

int main ()
{
    std::thread t1(func);
    std::thread t2(func);
    t1.join();
    t2.join();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

http://www.cplusplus.com/reference/map/map/end/

数据竞争访问容器(const和非const版本都不会修改容器).调用不访问包含的元素,但返回的迭代器可用于访问或修改元素.同时访问或修改不同的元素是安全的.

Jon*_*ely 11

我应该保护std::map::end还是保证它对于一个分配的容器总是相同的?

从技术上讲,任何对成员函数的调用都必须受到互斥锁的保护,如果它可能与任何非const成员函数同时发生.因此,如果任何线程可以插入或擦除元素,那么在end()不锁定互斥锁的情况下调用是不安全的.

我可以使用static auto const map_it_end = map1.end();不受保护的此类物品std::mutex吗?

在某些情况下,您可以缓存过去的迭代器,因为std::map插入和擦除不会使a的过去的迭代器无效,只能通过交换或移动映射.

但你为什么要这样做?缓慢的操作find()不是end(),所以如果你end()在仍然持有互斥锁的时候打电话,那么肯定会有效.

如果其他线程可能正在擦除元素,那么您需要在取消引用返回的迭代器时保持互斥锁,find()以确保它不会被另一个删除它引用的元素的线程无效.因此,end()当您已经锁定互斥锁时,拨打电话不会成为问题.