【问题标题】:Concurrency efficiency in C++C++ 中的并发效率
【发布时间】:2016-02-22 16:13:38
【问题描述】:

我有一个函数pushMessage()

void pushMessage(const char* msg, const int len)
{
    for (int i=0;i<len;++i)
        queue.push(*(msg+i))
}

有问题的队列是 tbb::concurrent_bounded_queue&lt;char&gt; 并且具有非常大的大小(假设无限)。

这个函数被两个线程调用。一个线程不断调用该函数,另一个线程偶尔调用一次。

确保队列的内容没有混合并发msg 的最有效方法是什么?我的第一个电话是使用互斥锁,但是我想听更多,因为我对并发世界还很陌生,而且我不想直接跳到我学到的第一件事上。非常感谢。

附: - 我可以访问 Boost 和 TBB 库。

编辑:队列是 char 类型,因为它用于逐字节发送消息以提高速度。以前的实现是一次发送全部消息。

【问题讨论】:

  • 这是读写器问题还是写器问题?
  • 作家兼作家。两个线程都写入队列。
  • 你所说的“为了速度”是什么意思???在这个实现中它会更慢
  • 更改后,是的,它会变慢。但我正在使用现有代码,以前从未发生过上述问题。我目前无法修改这个机制,因为很多都依赖于这个现有的实现。

标签: c++ multithreading concurrency tbb


【解决方案1】:

除了互斥体(或信号量或临界区——实际上都是一样的东西)之外,您别无选择。在当前设计中,没有其他方法可以确保消息的非交错。

不过,我确实质疑当前设计的智慧。当语义是整个消息时,为什么会有一个字符队列?将整个消息作为单个队列元素不是更好吗?

【讨论】:

    【解决方案2】:

    什么是确保队列内容最有效的方法 没有混合并发味精?

    根据我的经验(但主要是 c++11 之前的版本),当线程“很少”发生冲突时,任何互斥信号量都是“轻量级”。我由此推断,上下文切换一定是高成本的动作。如果临界区“解锁”,则互斥量检查的成本很小。

    通常,我使用(并推荐)互斥体,然后进行测试以查看行为是否足够。

    一个可能有用的比较

    a) 一个线程可以进入互斥锁保护的临界区多少次(即没有竞争)

    对比

    b) 使用相同的互斥锁可以完成多少线程上下文切换。

    【讨论】:

    • 在我的 ubuntu15.10、g++ 5.2.1、未优化和较旧的戴尔硬件上,a) std::mutex lock() 和 unlock() 大约需要 47 纳秒 b) a使用 std::mutex 强制执行 C++-11 线程切换大约需要 12,000 纳秒。
    【解决方案3】:

    一种可能的解决方案是使用boost::lockfree::queue&lt;std::string&gt;

    然后,您无需进一步同步即可推送和弹出整条消息。

    如果,如你所说,你必须使用字节,你可以试试boost::lockfree::spsc_queue&lt;char&gt;。那里有会员

    size_t write_available(size_t max_size) const
    size_type push(T const * t, size_type size)
    

    所以与互斥锁一起,您可以在pushMessage 方法中编写类似的内容

    {
        boost::lock_guard<boost::mutex> guard( mutex_);
        if( queue_.write_available( len ) )
            queue_.push( msg, len );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 2018-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      相关资源
      最近更新 更多