【问题标题】:Is it possible to implement lock free map in C++是否可以在 C++ 中实现无锁映射
【发布时间】:2012-12-29 14:39:01
【问题描述】:

我们正在开发基于 C/S 的网络应用程序,我们发现添加到 std::map 的锁太多,导致服务器性能变差。

我想知道是否可以实现无锁地图,如果可以,如何实现?那里有开源代码吗?

编辑: 实际上我们使用std::map来存储sockets信息,我们根据socket文件描述做了封装,包含一些其他必要的信息,比如ip地址、端口、socket类型、tcp或udp等。

总而言之,我们有一张全球地图说它是

map<int fileDescriptor, socketInfor*> SocketsMap, 

那么每个用于发送数据的线程都需要访问SocketsMap,并且在从SocketsMap读取或写入SocketsMap之前必须添加互斥锁,这样会因为添加这么多锁而大大降低整个应用程序的并发度到 SocketsMap。

为了避免并发级别问题,我们有两种解决方案:1. 分别存储每个 socketInfor* 2. 使用某种无锁映射。

我想找一种无锁地图,因为这个方案需要的代码改动比方案一要少很多。

【问题讨论】:

  • @WhozCraig 平心而论,这里特指 C++,而特指 C... 它们是非常不同的语言,尤其是当您考虑原子变量时。
  • @AlexChamberlain 说得很好,先生。我会拉下链接。
  • 如果您需要一个关联容器,但不需要排序,使用像std::unordered_map 这样的哈希可能更简单。即使使用当前的粗锁定(特别是如果您可以将任何昂贵的哈希计算移到锁定部分之外),它可能会更快,但我怀疑偶尔昂贵的重新哈希也比偶尔的重新平衡更容易处理,对于乐观者无锁版本。
  • 读者与作者的比例是多少?
  • @brianbeuning 我编辑了帖子,请参阅编辑部分。

标签: c++ algorithm dictionary lock-free


【解决方案1】:

实际上有一种方法,虽然我自己没有实现它,但有一篇来自著名 C++ 专家 Andrei Alexandrescu 的关于 lock free map using hazard pointers 的论文。

【讨论】:

  • 请注意,危险指针已获得专利,因此您可能无法在生产代码中使用它。知识产权不是很好吗?
  • 谢谢。我已经编辑了帖子以添加更多信息,您有更多建议吗?
  • 根据新信息,我相信您在架构层面上已经偏离了方向。如果您为每个客户端使用一个线程,您将永远无法很好地扩展它,请查看前摄器模式以获取更多详细信息。如果这需要大量工作,那么可能是一个简单的解决方法,可以让您获得额外的收益,那就是使用多个地图:即std::map&lt; int, socketInfor* &gt; info[10]; mutex mutexes[10]; ... mutexes[ fileDesc % 10 ].lock(); info[ fileDesc % 10 ][ fileDesc ]; ...。在任何情况下,自行滚动无错误无锁地图可能需要大量时间来验证和调试。
【解决方案2】:

您可以使用 optimistic designtransactional memory 实现地图。

如果两个操作同时寻址映射并且一个正在更改映射结构的可能性相对较小,并且您不希望每次都锁定开销,则此方法特别有效。

但是,有时会发生冲突,您必须以某种方式导致它(通常通过回滚到上一个稳定状态并重试操作)。

如果您的硬件支持足够好的原子操作 - 这可以通过 Compare And Swap (CAS) 轻松完成 - 您可以单独更改参考(并且无论何时更改地图,您都在使用地图的副本,而不是原始地图,并仅在您提交时将其设置为主要)。

【讨论】:

    【解决方案3】:

    HashMap 会适合吗?看看Intel Threading Building Blocks,他们有一个有趣的并发地图。我不确定它是否无锁,但希望您对良好的多线程性能感兴趣,而不是特别关注无锁。你也可以检查CityHash lib

    编辑:

    其实TBB的hash map并不是无锁的

    【讨论】:

      【解决方案4】:

      我很惊讶没有人提到它,但是 Click Cliff 实现了一个无需等待的hashmap in Java,我相信它可以移植到 C++,

      【讨论】:

        【解决方案5】:

        如果你使用C++11,可以看看facebook/folly的AtomicHashMap

        【讨论】:

        • 这可能不是 OP 想要的。您链接到的地图并非完全无锁。来自文档: AHArray 是一个固定大小的 value_type 单元的连续块。写入单元格时,键被锁定,而记录的其余部分被写入。
        【解决方案6】:

        是的,我使用“拆分有序列表”概念在 C++ 中实现了Lock-Free Unordered Map (docs)。它是一个自动扩展容器,支持 64 位 CAS 上的数百万个元素,没有 ABA 问题。在性能方面,它是beast(参见第 5 页)。 extensively tested 拥有数百万个随机操作。

        【讨论】:

        • 这看起来很可爱。但是,它依赖于自 3.4 版以来似乎已损坏的 clang(我目前在 3.7 上)。它无法找到系统包含文件。我没有足够的时间对此进行进一步研究。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-30
        • 1970-01-01
        • 2010-09-20
        • 2011-07-09
        • 1970-01-01
        • 2017-06-02
        • 1970-01-01
        相关资源
        最近更新 更多