【问题标题】:size functions and thread-safety in C++C++ 中的大小函数和线程安全
【发布时间】:2012-01-26 17:51:16
【问题描述】:

我想知道大小函数(大小、长度或其他)是否是线程安全的?据我了解,他们通常只返回一些私人大小的成员。我真的怀疑他们会做任何计算。它们都被标记为 const 但它们是线程安全的吗?例如 std::list::size?

我有一个用于写入的锁保护功能和另一个用于读取的功能(也有锁保护),但我想知道我的 count 功能是否也应该被锁保护? IMO,这看起来像是在浪费响应时间。如果同时从列表中删除某个成员(尽可能相同),我认为它不会破坏任何迭代器或失败。

【问题讨论】:

  • count 正在阅读。如果锁定其他读取操作,为什么不锁定count?它有什么特别之处?

标签: c++ list thread-safety constants


【解决方案1】:

是的,它需要被锁保护。假设您的实现的 std::list::size 是一个 32 位值,但在您的平台上,32 位读取不是原子的,它们需要 2 个 16 位读取。在这种情况下,第二个线程可能会在第一次读取发生后中断正在读取大小的第一个线程,更新大小变量,然后当第二次 16 位读取发生时,您可能会得到一个真正混乱的大小值。

【讨论】:

  • 这解释了为什么它不是线程安全的。谢谢。
  • @Pijusn 和 Kerrek SB,答案完全矛盾。
  • 即使在 2012 年,还有多少 16 位系统在使用?最好说将size() 视为线程安全的危害可移植性
【解决方案2】:

不,它们不是线程安全的。标准容器根本不是线程安全的。

然而,线程安全性是有限的:如果每个线程都访问一个不同的元素,并且在任何给定时间两个不同的线程都没有访问任何元素,那么这很好。但是,任何改变容器本身的操作(插入、擦除)都不是线程安全的,必须同步。因此,迭代器和引用可能会失效,size() 也会受到类似影响。

换句话说,如果你将所有改变容器的操作与不改变容器的操作分开,那么当你没有改变时,你可以安全地从多个线程调用size()

【讨论】:

  • 标准容器“根本不是线程安全的,句号”的说法非常具有误导性!它们提供了一种非常合理的线程安全形式。仅仅因为有些人希望一种线程安全,他们可以在不关心线程的情况下获得所有好处,但这并不意味着他们不是线程安全的!人们不理解即使是对原始值的访问也需要同步这一事实是他们在线程中遇到的问题的一部分。
猜你喜欢
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多