我需要通过访问/更改给定索引处的数组以及迭代数组的元素来对std::array
进行
操作。
假设数组元素是线程安全对象的shared_ptr。从不同线程操作数组时,是否存在线程安全问题?
Context:如何使下面的线程安全,
#include <array>
#include <memory>
struct SafeQueue
{
void push(const double d) {};
bool try_pop(double& d) {};
};
struct Broadcaster
{
std::array<std::shared_ptr<SafeQueue>, 10> m_queues;
void broadcast(const double d)
{
for(auto p : m_queues)
if(p) p->push(d);
}
bool addQueue(const std::shared_ptr<SafeQueue>& q)
{
for(auto& p : m_queues)
if(!p)
{
p = q;
return true;
}
return false;
}
};
假设我们从不同的线程调用
broadcast
和 addQueue
。
我想我可以用原子索引来解决这个问题,但我在想是否有更好的方法。
STL 容器(有一些例外)不是线程安全的。
我知道人们普遍不赞成给出可以被解释为个人意见的具体建议,但我认为这个问题值得例外。
我们不应该编写自己的并发代码,就像我们不应该重新发明日期处理和加密处理代码一样,除非我们拥有这些任务所需的特定领域知识。
如果您对项目中的第 3 方代码感到满意,则可以使用这个编写良好、经过充分测试、现代且快速的 C++ 单生产者、单消费者无锁队列,称为 readerwriterqueue。
如果您需要多个生产者和消费者,同一个人已经编写了一个用于 C++ 的工业级无锁队列,称为并发队列。
作为替代方案,微软确实在其并行模式库中提供了一些并发容器,尽管我不知道它们的性能如何。
免责声明: 我与这些无锁队列的作者没有任何关系。我只是在我的项目中使用它,原因与我需要执行 AES 加密时使用 OpenSSL 的原因相同。