boost::unordered::concurrent_node_map 使用指南

Boost 的 concurrent_node_map 是一个线程安全的哈希表,支持高并发操作。以下是使用指南及示例:


基本用法

1. 头文件与命名空间

#include <boost/unordered/concurrent_node_map.hpp>
using namespace boost::unordered;

2. 创建实例

concurrent_node_map<int, std::string> map;

3. 插入元素

// 插入键值对
map.insert({1, "one"});
map.emplace(2, "two");

// 使用 try_emplace(键存在则不插入)
bool inserted = map.try_emplace(3, "three");

4. 访问元素


// 使用 visit 访问元素(原子操作)
map.visit(1, [](auto& val) {
    std::cout << val.second << "\n"; // 输出 "one"
});

// 也可以使用显示的遍历对象
map.visit(1, [](std::pair<const int, std::string>& val) {
    std::cout << val.second << "\n"; // 输出 "one"
});
// 注意:对象的key需要使用const修饰

// 检查键是否存在
if (map.contains(2)) {
    std::cout << "Key 2 exists.\n";
}

5. 删除元素

size_t erased = map.erase(1); // 返回删除的数量

6. 并发遍历

// 遍历所有元素(线程安全)
map.visit_all([](auto& pair) {
    std::cout << pair.first << ": " << pair.second << "\n";
});

多线程示例

#include <boost/unordered/concurrent_node_map.hpp>
#include <thread>
#include <vector>

using namespace boost::unordered;

void insert_work(concurrent_node_map<int, int>& map, int start) {
    for (int i = start; i < start + 1000; ++i) {
        map.insert({i, i * 10});
    }
}

void read_work(concurrent_node_map<int, int>& map, int key) {
    map.visit(key, [](auto& val) {
        std::cout << "Key " << val.first << " = " << val.second << "\n";
    });
}

int main() {
    concurrent_node_map<int, int> map;

    // 启动多个线程插入数据
    std::vector<std::thread> threads;
    for (int i = 0; i < 10; ++i) {
        threads.emplace_back(insert_work, std::ref(map), i * 1000);
    }

    // 启动读取线程
    std::thread reader([&map] {
        for (int i = 0; i < 10000; ++i) {
            read_work(map, i);
        }
    });

    // 等待所有线程完成
    for (auto& t : threads) t.join();
    reader.join();

    return 0;
}

关键特性

  1. 线程安全:

    • 所有操作(插入、删除、访问)可并发执行,无需外部锁。
    • 内部通过细粒度锁或无锁技术实现并发。
  2. 原子操作:

    • visit/cvisit 保证在访问期间元素状态不变。
    • try_emplace 等操作保证原子性。
  3. 高性能设计:

    • 开放寻址法减少内存开销。
    • 批量操作(如 visit_all)优化遍历效率。

注意事项

  • 哈希函数与比较器:需确保线程安全,默认使用 boost::hash 和 std::equal_to。
  • 内存分配器:推荐使用线程安全的分配器(如默认的 std::allocator)。
  • 异常安全:大多数操作提供强异常保证。

高级操作

1. 合并哈希表

concurrent_node_map<int, std::string> other_map;
other_map.insert({4, "four"});
map.merge(other_map); // 合并 other_map 到 map

2. 条件删除

// 删除值为偶数的键
map.erase_if([](auto& pair) {
    return pair.second % 2 == 0;
});

3. 提取节点

auto node = map.extract(2); // 提取键为 2 的节点
if (!node.empty()) {
    // 修改节点值
    node.mapped() = "new two";
    map.insert(std::move(node)); // 重新插入
}

通过上述示例和说明,可以安全地在多线程环境中使用 concurrent_node_map 实现高效的数据存取。

posted @ 2025-04-08 16:14  BlackSnow  阅读(140)  评论(0)    收藏  举报