【发布时间】:2016-07-05 23:28:30
【问题描述】:
我使用std::map 并获得一个我可以使用的元素:http://www.cplusplus.com/reference/map/map/
iterator find (const key_type& k);mapped_type& at (const key_type& k);mapped_type& operator[] (const key_type& k);
也: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 保护的东西吗?
#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;
}
http://www.cplusplus.com/reference/map/map/end/
数据竞争 容器被访问(既不是 const 也不是 非常量版本修改容器)。没有包含的元素 通过调用访问,但返回的迭代器可用于访问 或修改元素。同时访问或修改不同的 元素是安全的。
【问题讨论】:
-
你有没有尝试在地图末尾插入一个新元素并测试 map::end() 是否改变了?
-
无论如何,与
map_it_end而不是map1.end()相比,您可能不会节省任何可衡量的性能。 -
地图会改变吗?如果没有,并且您只进行查找而不插入或删除元素,那么您不需要互斥锁。并发非修改访问是线程安全的。
-
@Tim Straubinger
map::end()没有改变。但这将适用于所有编译器吗? ideone.com/tATn0H -
@Jonathan Wakely 还有其他线程的插入和删除。
标签: c++ multithreading c++11 concurrency c++14