【问题标题】:Implementation of Concurrent Queue + map in c++C++中并发队列+map的实现
【发布时间】:2014-09-21 12:51:48
【问题描述】:

我不太擅长数据结构,所以这可能是个非常愚蠢的问题。我正在寻找一种方法来实现队列+地图的混合行为。

我目前在多线程单生产者单消费者进程中使用来自www.threadingbuildingblocks.orgtbb::concurrent_bounded_queue(记录在Intel's developer zone)。该队列具有市场数据报价对象,并且该过程的生产者端实际上对时间高度敏感,因此我需要一个以市场数据标识符(例如 USDCAD、EURUSD)为键的队列。价值点(通过unique_ptr)指向我为此密钥收到的最新市场数据报价。

所以,假设我的队列有 5 个元素用于 5 个唯一标识符,突然我们在队列中的第 3 位获得标识符的更新市场数据报价,然后我只存储最新值并丢弃我之前拥有的值.所以,基本上我只是将我的 unique_ptr 移动到这个键的新市场数据报价。

就像它与concurrent_bounded_queue<pair<string, unique_ptr<Quote>>> 相似,但键控于该对的第一个元素。

我不确定这是否已经在第三方库中可用(可能是 tbb 本身),或者如果它是标准数据结构,它被称为什么。

我非常感谢您对此提供任何帮助或指导。

谢谢。

【问题讨论】:

  • 数据结构图有助于理解任务

标签: c++ multithreading data-structures concurrency tbb


【解决方案1】:

我能够解决这个问题如下:

我使用来自tbb 库的queuehashmap。现在,我将我的唯一标识符推送到 queue 而不是 Quote 上。我的hashmap 有我的唯一标识符作为键和引用作为值

所以,当我收到Quote 时,我会遍历queue 并检查queue 是否包含该标识符,如果包含,则将相应的Quote 直接插入hashmap 并执行不要在queue 上添加唯一标识符。如果没有,那么我将标识符推送到queue 和对应的Quote 哈希图中。这可确保我的 queue 始终作为唯一标识符集,并且我的 hashmap 具有可用于该标识符的最新 Quote

在消费者方面,我弹出queue 以获取我的下一个标识符并从hashmap 获取该标识符的报价。

这工作得非常快。如果我遗漏了任何隐藏的问题,请告诉我。

【讨论】:

  • 在非线程安全的情况下迭代 concurrent_queue。如果这不是问题,为什么要使用 concurrent_queue 而不是 std::queue?
【解决方案2】:

待定提供

  • concurrent_undordered_map:没有并发擦除,稳定的迭代器,没有元素访问保护;
  • concurrent_hash_map:具有并发擦除、并发操作使迭代器无效、通过“访问器”进行的每个元素访问管理

所以,如果问题 “It's like it is similar to concurrent_bounded_queue<pair<string, unique_ptr<Quote>>> but is keyed on the first element of the pair”表示建议对应的并发关联地图容器,这两个为您服务。基本上,您必须在同时擦除标识符的能力(hash_map)和同时遍历所有元素的能力(unordered_map)之间做出选择。 concurrent_hash_map 还简化了对您的情况有用的元素访问的同步。

【讨论】:

  • 是的。我正在查看concurrent_hash_map 并试图弄清楚如何在"new message received" 回调和相应的insert 之间进行通信到concurrent_hash_map。消费者端基本上会从hash_map 获取最新的Quote 并将其删除。因此,如果inserts 的速度快于erases 的速度,我仍然可以处理最新的报价。但是,这仍然没有类似队列的行为..对吗?困难的部分是将这个hash_mapQuotes 的传入队列集成。你怎么看?
  • 我仍然不确定我是否理解您想要实现的目标,Tony 没有回答您的问题(只是将向量替换为 hash_map..)?据我了解,我猜你不需要删除引号,如果时间戳比存储的时间戳更新,只需更新它们
【解决方案3】:

首先,观察我们可以很容易地写...

int idn_to_index(idn); // map from identifier to contiguous number sequence

...如果使用std::mapstd::unordered_map 没关系,在排序的std::vector 中进行二进制搜索,您自己的逐字符硬编码解析器......

那么制作人可以:

  1. 更新(使用互斥体)std::vector<unique_ptr<Quote>>[idn_to_index(idn)]

  2. 将索引发布到concurrent_bounded_queue<int>

消费者:

  1. 弹出索引

  2. 将 [index] 处 std::vector<unique_ptr<Quote>> 中的指针与其自己的最后一次看到的指针数组进行比较,如果它们不同,则处理引用

这里的想法不是要避免在队列中出现重复的特定于标识符的索引,而是要确保其中最陈旧的索引仍会触发对最新报价的处理,并且在数据完成之前,不那么陈旧的队列条目会被无害地忽略真的又更新了。

【讨论】:

    猜你喜欢
    • 2011-09-07
    • 2011-04-14
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多