【问题标题】:Is it possible to use mutex to lock an element in a vector not the whole vector?是否可以使用互斥锁来锁定向量中的元素而不是整个向量?
【发布时间】:2011-12-18 01:19:43
【问题描述】:

是否可以使用互斥锁来锁定向量中的元素而不是整个向量?

例如,给定一个向量 myVec; 将 10 个元素推回 myVec 中

  for (int i = 0; i < 10; ++i)
  {
          buffer myBuf = i; // actually myBuf is not necessarily int.
          myVec.push_back(myBuf);
  }

向量的每个元素都会被多个线程异步更改。 如何使用互斥锁只锁定 myVec 中的一个缓冲区,以便一个线程可以写入或读取一个元素;另一个可以同时读取和写入另一个元素?

谢谢

【问题讨论】:

  • 你能更准确地说明你必须做什么吗?我的意思是,也许更多细节?

标签: c++ multithreading vector mutex deadlock


【解决方案1】:

如果向量在启动时被初始化,它就像一个固定大小的数组,所以不需要锁定它。 如果你愿意,我更喜欢用 new[] 分配的数组。

如果说,threadN 只访问 fieldN 不需要任何锁,那么当多个线程尝试访问以读取和写入相同的资源时,就需要锁。

如果一个线程只访问一个资源进行读写,并且该资源没有被任何其他线程访问,那么绝对没有问题!你不需要任何锁。

如果一个资源只在只读模式下被多个线程访问,则不需要任何锁。

如果不清楚,在您的情况下,array[i] 是读/写资源,而 array 是共享只读资源。

如果您需要同步每个元素,则需要为每个元素设置一个互斥锁。 如果有 n 个资源被 m 个线程访问,则需要使用 n 个互斥锁来锁定这些资源。它们并不昂贵。

如果您的资源确实太多,您可以锁定数组的一部分:单个互斥锁将使您的应用程序成为单线程,但您可以每 10 个项目分配一个互斥锁,例如。通过这种方式,您可以减少互斥体的数量,但同时您可以确保不会有太多线程不会停顿在一起。

【讨论】:

  • 向量的每个元素可以是一个或多个双精度浮点数。线程通过读取和写入指定索引的元素来交换数据(例如,每个线程只需要读取或写入向量中固定位置的元素)。
  • 我想为向量中的每个元素添加一个互斥锁,以便在一个时间点只能由一个线程读取或写入该元素。
  • 那么正如我之前所说,每个元素都需要一个互斥锁:)
  • 我同意@SalvatorePreviti - 在你的浮点类中粘贴一个互斥锁/futex,并在ctor中创建它。在 FP 方法/getter/setter 的开始和结束处获取/释放互斥锁。正如其他海报所说,如果您需要添加/删除对象,则需要锁定整个向量以进行添加/删除/迭代/等,否则,您应该可以将每个实例锁定在自己的互斥体上。
【解决方案2】:

你想要的比你想象的更简单也更难:

如果你的容器作为一个整体没有改变,即没有插入或擦除,那么标准库容器已经提供了有限类型的线程安全,即允许不同的线程读取或修改不同 容器元素,即只要不超过一个线程访问任何给定元素。

另一方面,如果将容器作为一个整体进行修改,那么您几乎没有安全保障:根据容器的类型,您绝对必须了解引用和迭代器失效。 如果您知道对元素的引用或迭代器不受影响,则上述适用(分别适用于引用或取消引用的迭代器)。如果没有,那么除了重新获取对所需元素的新引用之外,您别无希望。

【讨论】:

  • 好吧,他说向量不会只包含整数,所以我猜,它可以包含超过 4 个字节的结构或对象,所以读\写操作不能是原子的,一个 volatile 字段是不够的。
  • 向量的每个元素都会被多个线程异步改变。
  • @user1000107:但听起来矢量本身不会改变。而且由于您在其中存储的不仅仅是整数,您可以在向量中的每个项目内填充一个指向关联互斥锁的指针。您不能直接在其中存储互斥锁,因为互斥锁可能不会被复制或移动,并且这两者都是向量中的对象所必需的。
  • @Omnifarious - 为什么不能复制或移动互斥锁句柄?即使这是真的,如果移动了向量中的对象实例,则不需要复制/移动对象中的互斥体 - 对象数据成员不会移动。
  • @MartinJames:因为互斥锁不仅仅是一个句柄。例如,在 Linux 上,它实际上是保存互斥锁状态的内存区域,包括操作系统级别的详细信息,如果它被争用,谁在等待它。每当向量改变时,向量中的东西可能会随机移动。不允许将内容放入无法复制(或在 C++11 中移动)的向量中是有原因的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
  • 2011-09-06
  • 2011-02-14
  • 2021-04-16
相关资源
最近更新 更多