【问题标题】:Simple mutex protected queue vs. thread safe queue in C++简单的互斥保护队列与 C++ 中的线程安全队列
【发布时间】:2020-10-07 15:08:05
【问题描述】:

我想在我的程序中使用一个简单的线程安全 std::queue,它有多个线程访问同一个队列。我首先想到的是使用互斥锁保护队列操作,如下所示:

/*Enqueue*/
mutex.lock();
queue.push();
mutex.unlock();

/*Dequeue*/
mutex.lock();
val = queue.front
mutex.unlock();
/*some operation*/
mutex.pop();

我已经看到了许多使用条件变量实现线程安全队列的强大实现。 https://stackoverflow.com/a/16075550/3598205 。如果我只有两个线程访问同一个队列,性能会有显着差异吗?

【问题讨论】:

  • 这完全取决于访问模式。如果您关心性能,则需要进行概要分析。

标签: c++ c++11


【解决方案1】:

互斥锁和条件变量做两种不同的事情,尽管它们经常一起使用。

要确保一次只有一个线程可以访问资源,请使用互斥锁。您发布的代码显示了一个示例。

要阻塞一个工作线程直到它有事情要做,让它等待一个条件变量(然后由另一个提供某种工作项的线程发出信号)。 cppreference 有一个例子。

在编写多线程代码时,您的第一个想法应该是编写健壮、安全的代码。很容易犯错误,特别是如果您是该领域的新手,而且错误很难诊断,因为它们会导致零星的、不可预测的错误。以后再担心性能。

【讨论】:

  • OP 似乎在一个安全的简单互斥队列和一个大多数时间不需要锁的花哨的无锁结构之间犹豫不决。后者更先进,但更难维护、调试和测试。我会说他们需要检查他们的实际需求。
【解决方案2】:

您的申请将受到一件主要事情的限制。我们称之为瓶颈。根据我的经验,我见过的 90% 的应用程序都受到总线带宽的限制,向/从主内存/CPU 传输内存。

不同的应用会有不同的瓶颈。它可能是 GPU 性能或磁盘访问。可能是原始 CPU 功率,也可能是争用访问上面的队列。

很可能,互斥锁与花哨的无锁队列一样好。但你不知道,直到你配置文件。

您的应用程序很可能会受到对该队列的访问的严格限制。例如,如果您的应用程序是金融机构的低延迟市场数据交换,并且队列正在持有买入/卖出指令,那么它将有所作为。这两个线程可能会不断地写入具有几百个项目的队列上的不同位置(因此,在不同的内存页面上)。

或者可能是您的应用程序总是在 GPU 上等待渲染帧,而队列保存玩家武器更改,renderinggameplay 线程只访问几个每帧的次数。

配置文件并检查。

【讨论】:

  • 如果您查看链接的问题,请注意@quantdev(量化金融开发人员?)确切地建议来自 Boost 的无锁队列。但除了这样的小众案例,互斥体也可以。
猜你喜欢
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2023-03-04
  • 2013-02-23
  • 2012-11-05
  • 2010-11-15
相关资源
最近更新 更多