c – std :: map :: end thread-safe并保证它对于同一个容器总是相同的吗?

前端之家收集整理的这篇文章主要介绍了c – std :: map :: end thread-safe并保证它对于同一个容器总是相同的吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用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并通过lock std :: mutex保护它.

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

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

我可以使用像这样的静态自动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;
}

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

Data races The container is accessed (neither the const nor the
non-const versions modify the container). No contained elements are
accessed by the call,but the iterator returned can be used to access
or modify elements. Concurrently accessing or modifying different
elements is safe.

解决方法

Should I protect std::map::end or is guaranteed that it always the same for one allocated container?

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

Can I use something like this static auto const map_it_end = map1.end(); which is not protected by std::mutex?

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

但你为什么要这样做?缓慢的操作是find()而不是end(),所以如果你仍然持有互斥锁时调用end()那么它肯定有效.

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

猜你在找的C&C++相关文章