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

C++ C/C++;带线程的数组-我需要使用互斥锁还是锁?,c++,c,arrays,multithreading,mutex,C++,C,Arrays,Multithreading,Mutex,我不熟悉使用线程,并且读过很多关于如何共享和保护数据的书。但我也没有真正掌握如何使用互斥锁和锁来保护数据 下面是我将要解决的问题的描述。需要注意的重要一点是,这将是时间关键的,因此我需要尽可能减少开销 我有两个固定大小的双数组 第一个数组将为后续计算提供数据。 线程将从中读取值,但它永远不会被修改。任何线程都可以在某个时间读取元素 第二个数组将用于存储线程执行的计算结果。此数组的一个元素将仅由一个线程更新,并且可能仅在结果值为时更新一次 这是写给它的 我的问题是: 每次从只读阵列访问数据

我不熟悉使用线程,并且读过很多关于如何共享和保护数据的书。但我也没有真正掌握如何使用互斥锁和锁来保护数据

下面是我将要解决的问题的描述。需要注意的重要一点是,这将是时间关键的,因此我需要尽可能减少开销

我有两个固定大小的双数组

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

  • 第二个数组将用于存储线程执行的计算结果。此数组的一个元素将仅由一个线程更新,并且可能仅在结果值为
    时更新一次 这是写给它的

我的问题是:

  • 每次从只读阵列访问数据时,我真的需要在线程中使用互斥吗?如果是,你能解释一下原因吗

  • 当线程写入结果数组时,我是否需要在线程中使用互斥体,即使这将是唯一一个写入此元素的线程

  • 我应该使用原子数据类型吗?如果我使用原子数据类型,会不会有很大的时间开销

  • 这类问题的许多答案似乎是-不,如果变量对齐,就不需要互斥。在本例中,我的数组元素是对齐的,还是有办法确保它们对齐

  • 该代码将在64位Linux上实现。我计划使用Boost库进行多线程处理

    我已经仔细考虑了这一点,并在网上搜索了几天,一旦发布,答案和清晰的解释在几秒钟内就回来了。有一个“公认的答案”,但所有的答案和评论都同样有用

  • 每次从只读阵列访问数据时,我真的需要在线程中使用互斥吗?如果是,你能解释一下原因吗
  • 不会。因为数据从未修改过,所以不会有同步问题

  • 当线程写入结果数组时,我是否需要在线程中使用互斥体,即使这将是唯一一个写入此元素的线程
  • 视情况而定

  • 如果任何其他线程要读取该元素,则需要同步
  • 如果任何线程可能修改向量的大小,则需要同步
  • 在任何情况下,注意不要通过不同的线程大量写入相邻的内存位置。这可能会破坏性能。请参阅“虚假共享”。考虑到,您可能没有太多的内核,因此没有太多的线程,并且您说写操作只完成一次,但这可能不会是一个重大问题

  • 我应该使用原子数据类型吗?如果我使用原子数据类型,会有很长的时间吗
  • 如果使用锁(互斥锁),则不需要原子变量(而且它们确实有开销)。如果不需要同步,则不需要原子变量。如果您需要同步,那么在某些情况下可以使用原子变量来避免锁定。在哪些情况下可以使用原子而不是锁。。。这个问题更复杂,我认为超出了这个问题的范围

    根据评论中对您的情况的描述,似乎根本不需要同步,因此不需要原子或锁

  • …在本例中,我的数组元素是对齐的,还是有办法确保它们对齐

  • 正如Arvid所指出的,您可以使用c++11中引入的关键字请求特定的对齐。在c++11之前,您可以求助于特定于编译器的扩展:

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

  • 不需要。不需要互斥体,因为线程只读取数组

  • 不会。因为每个线程只写入一个不同的内存位置,所以不可能存在争用条件

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


  • 你在正确的轨道上

    1) 对于第一个数组(只读),不需要为其使用互斥锁。由于线程只是读取而不是更改数据,因此一个线程不可能损坏另一个线程的数据

    2) 这个问题让我有点困惑。如果您知道线程1只将一个元素写入阵列插槽1,线程2只将一个元素写入阵列插槽2,那么您就不需要互斥锁。然而,我不确定你是如何实现这个属性的。如果我的上述声明不适合您的情况,您肯定需要一个互斥锁

    3) 鉴于原子的定义:

    原子类型是封装一个值的类型,该值的访问保证不会导致数据争用,并可用于同步不同线程之间的内存访问

    注意,互斥锁是原子锁,这意味着只需要一条汇编指令就可以获取/释放锁。如果需要2个装配说明来抓取/释放锁,则锁不是螺纹安全的。例如,如果线程1试图获取锁并切换到线程2,那么线程2将获取锁

    使用原子数据类型会减少开销,但不会显著降低

    4) 我不知道你怎样才能保证你的变量是线性的。因为线程可以在程序中随时切换(操作系统决定线程切换的时间)


    希望这有帮助

    您唯一需要使用锁的时间是在共享资源上修改数据时。如