【问题标题】:C++ thread safe variables without std::atomic [duplicate]没有std :: atomic的C ++线程安全变量[重复]
【发布时间】:2021-08-13 16:13:59
【问题描述】:

如果我有一个包含一些成员的结构,并且我希望有不同的线程读入这些结构。在这种情况下,我不需要做任何事情,因为我只阅读,但是如果我想 write 给成员,我是否必须使用原子并强制每个人在任何地方显式加载原子?就因为我偶尔写的一篇文章?

【问题讨论】:

  • 如果这些写入和读取可能同时发生,那么,您需要原子。请注意,从 C++20 开始,您可以使用 std::atomic_ref,这使变量能够具有非原子类型。
  • 顺便说一句,基本相同的问题不要问两次。这似乎是 stackoverflow.com/q/67686525/580083 的副本。相反,请按照其 cmets 中的建议编辑原始问题。
  • 第一句:“读入这些结构的不同线程”——“读取”还是“写入”?或者两者兼而有之?请澄清这一点,并从标题中删除“C++”,这是标签的用途。

标签: c++ multithreading atomic


【解决方案1】:

将变量设为私有并通过 getter 和 setter 访问它们,并使用 std::scoped_lock 保护它们的访问:

在 cpp 中:

std::mutex aMutex;

int getInteger() const
{
  std::scoped_lock<std::mutex> aLock(aMutex);
  return m_integer;
}

void setInteger(int iInteger)
{
  std::scoped_lock<std::mutex> aLock(aMutex);
  m_integer = iInteger;
}

【讨论】:

  • 主题如何?
  • 如果只有一个写入器,则不需要互斥锁。相反,可以使用原子变量。 OP 专门要求这种情况。
  • @ciamej 确实有一个作家,但也有一个读者(或几个读者)。如果他们可以同时读取作者修改变量,则需要一个互斥体(或使用原子变量)。
  • 是的,这就是我的意思 - 使用原子变量时不需要互斥体 ,并且没有充分的理由使用它,因为原子存储/加载要好得多性能明智,更自然。
【解决方案2】:

如果你有多个读写器,你应该使用同步方法。

在您的情况下,因为您的读写顺序不正确,您应该同步它们。想象一下,如果您运气不好,您同时读取和写入值,您的读取器线程将快速读取并将值存储在寄存器(或其他位置)中,然后您立即写入新值,因此您的值更新并且先前的值消失了。

最著名的同步方法是互斥锁。 示例:

#include <mutex>
std::mutex mutex;

mutex.lock();
//enter critical section
mutex.unlock(); //exit critical section

另一个很好的同步方法是读写锁。 在这种方法中,如果您要读取值,您可以多次锁定并从多线程读取值,但如果您要在写入端调用锁定时写入,则其他线程无法读取或写入值,因为它当前正在写入中。

另一种很好的同步方法是自旋锁,在这种方法中,您只需运行繁忙循环,直到您可以访问操作变量。这种方法的好处是,因为我们运行繁忙的循环,所以它比互斥锁更快,因为在互斥锁中你切换到内核模式很慢(但要注意你应该只持有自旋锁一小段时间)

它们是许多其他同步方法,但我建议您使用互斥锁或原子变量。

【讨论】:

  • 主题如何?
猜你喜欢
  • 2015-03-03
  • 2011-01-24
  • 1970-01-01
  • 2015-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
相关资源
最近更新 更多