【发布时间】:2017-11-24 19:09:09
【问题描述】:
基本上,我需要使用来自同时读取的数千个文件的数百万个关键条目(或多或少 5000 万个订单)填充 std::map。这些键将指向的值将从堆中分配(std::bitset 类型)。
std::map<std::string,std::bitset<BITSET_SIZE>*> my_map;
-
我的第一个问题是:我不想要两个线程(首先检查一个 key 存在,如果不存在,)从堆中分配空间。 因为我只能持有一个指针,而其他分配将 导致内存泄漏,因为我无法跟踪它们。
//count should be thread-safe, since it's defined as const in <map> header file if(my_map.count(key) == 0){ //some other thread may have initialized the key in the mean time my_map[key] = new std::bitset<BITSET_SIZE>(); //Now I will lose the pointer to previous heap allocation from other thread }一种解决方案是使用一些互斥机制,例如
boost::unique_lock或boost::shared_lock的一些巧妙组合 和 boost::unique_lock 以提高性能,我很高兴听到你的想法。 - 想象我已经完成了第一部分,意思是;在没有内存泄漏的情况下同时初始化 my_map 的键,任务的第二部分是同时操作值 (
std::bitset)。为此,我认为应该没有任何问题,因为根据我的设置,可以保证没有两个线程同时在同一个键上工作。 (任何线程都不会为 my_map 的键添加新键或从底层树结构中删除键)
【问题讨论】:
-
您使用
std::bitset<BITSET_SIZE>*而不仅仅是std::bitset<BITSET_SIZE>有什么原因吗? -
我希望能够在程序的整个生命周期中保留此映射和位集,并且我认为它应该从堆中分配,因为一旦线程函数的范围超出,我就不能不再信任在堆栈上为该函数分配的位集。
-
通常没有理由在地图中使用指针。你能仔细检查一下你是否绝对需要它吗?将 bitset 插入映射时,您不需要它的原始内存地址。每个人都可以访问该地图,因此每个人都可以访问该位集。另外,如果保证两个线程不会访问同一个key,那么也不会有任何内存泄漏。
-
@SorooshBateni 那么在第一阶段没有这样的保证,所以可能会发生内存泄漏!想象一下,我有一堆同时读取的文件,为简单起见,每个文件都有以下格式的行: key -> metadata 。相同的密钥可以出现在所有这些文件中。但我只想在第一次看到它时插入键来映射和关联一个位集。如果另一个线程从另一个文件中读取相同的密钥,那么在第一次出现之后,它就会被忽略!现在如果两个线程遇到同一个不存在的键,我就会有泄漏问题。
标签: c++ multithreading c++11 memory-leaks mutex