带线程的C/C++数组 - 我需要使用互斥锁还是锁?

Bar*_*ear 10 c c++ arrays multithreading mutex

我是使用线程的新手,并且已经阅读了很多关于如何共享数据和保护数据的知识.但是我还没有真正掌握何时需要使用互斥锁和锁来保护数据.

以下是我将要解决的问题的描述.需要注意的重要一点是它对时间至关重要,因此我需要尽可能减少开销.

我有两个固定大小的双阵列.

  • 第一个数组将为后续计算提供数据.线程将从中读取值,但永远不会被修改.任何线程都可以在某个时间读取元素.

  • 第二个数组将用于存储
    线程执行的计算结果.此数组的元素将仅由一个线程更新,并且可能仅在将结果值
    写入其中时才更新一次.

我的问题呢?

  1. 每次从只读数组访问数据时,是否真的需要在线程中使用互斥锁?如果是这样你能解释原因吗?

  2. 我是否需要在写入结果数组时在线程中使用互斥锁,即使这将是唯一写入此元素的线程?

  3. 我应该使用原子数据类型吗?如果我这样做会有任何重要的时间吗?

  4. 这类问题的答案似乎很多 - 不,如果您的变量是对齐的,则不需要互斥锁.我的数组元素在这个例子中是否可以对齐,还是有某种方法可以确保它们是?

代码将在64位linux上实现.我打算使用Boost库进行多线程处理.

感谢所有的回复和评论, 我一直在仔细研究这个问题并在网上看了好几天,并且一旦发布了答案,清楚的解释就会在几秒钟之内回来.有一个"已接受的答案",但所有的答案和评论都同样有用.再次感谢

eer*_*ika 7

  1. 每次从只读数组访问数据时,是否真的需要在线程中使用互斥锁?如果是这样你能解释原因吗?

不会.因为数据永远不会被修改,所以不会出现同步问题.

  1. 我是否需要在写入结果数组时在线程中使用互斥锁,即使这将是唯一写入此元素的线程?

要看.

  1. 如果任何其他线程要读取该元素,则需要同步.
  2. 如果任何线程可能修改向量的大小,则需要同步.

在任何情况下,请注意不要通过不同的线程写入相邻的内存位置.这可能会破坏性能.请参阅"虚假共享".考虑到,你可能没有很多内核,因此没有很多线程,你说只写了一次,但这可能不会成为一个重大问题.

  1. 我应该使用原子数据类型吗?如果我这样做会有任何重要的时间吗?

如果使用锁(互斥锁),则不需要原子变量(并且它们确实存在开销).如果不需要同步,则不需要原子变量.如果需要同步,则可以使用原子变量来避免某些情况下的锁定.在哪些情况下你可以使用原子而不是锁...更复杂,我认为超出了这个问题的范围.

鉴于您在评论中对您的情况的描述,似乎根本不需要同步,因此没有原子和锁.

  1. ...这个示例中的数组元素是否会对齐,还是有某种方法可以确保它们是?

正如Arvid所指出的,您可以使用c ++ 11中引入的alginas关键字请求特定的对齐方式.在前c ++ 11中,您可以使用编译器特定的扩展:https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Variable-Attributes.html


P.P*_*.P. 4

在给定的两个条件下,不需要互斥体。请记住,每次使用互斥体(或任何同步构造)都会产生性能开销。因此,您希望尽可能避免它们(当然,不影响正确的代码)。

  1. 不需要。不需要互斥体,因为线程仅读取数组。

  2. 不会。由于每个线程仅写入不同的内存位置,因此不可能出现竞争条件。

  3. 不。这里不需要对对象进行原子访问。事实上,使用原子对象可能会对性能产生负面影响,因为它阻止了优化的可能性,例如重新排序操作。