我可以使用 std::vector::swap 来修改共享向量吗?

Can I use std::vector::swap to modify a shared vector?

本文关键字:共享 修改 向量 swap 可以使 std vector 我可以      更新时间:2023-10-16

我正在开发多个线程读取访问具有大量(和大型(数据的单个std::vector的软件。

我对多个头访问单个对象的复杂性有一些基本的了解,并且通过使用互斥锁可以大大简化事情。

就我而言,修改现有对象比复制它要昂贵得多。所以我正在考虑创建一个副本,修改副本(同时不持有互斥锁(和 然后将其交换回共享对象。

我不能使用 C++11,所以我无法访问移动操作,但我的理解是gcc使用非常高效的std::vector::swap(),可与移动操作(在速度方面(相媲美。

我在想这样的事情:

pthread_mutex_t mtx;
class bigdata_t { ... };
std::vector<bigdata_t> shared_vec; // accessed by multiple threads
void modify_bigdata()
{
pthread_mutex_lock(&mtx);
std::vector<bigdata_t> tmp_vec = shared_vec; // create copy
pthread_mutex_unlock(&mtx);
/*
* Here, apply expensive modifications to tmp_vec
*/
pthread_mutex_lock(&mtx);
shared_vec.swap(tmp_vec); // this is very fast and does not copy data
pthread_mutex_unlock(&mtx);
}

modify_bigdata()仅由单个线程调用,因此这基本上是单编写器/多个读取器的方法。

它运行得非常快,但是将数据交换回共享向量感觉就像作弊一样。

我的问题是:
这种方法是否正确且线程安全?

假设您交换了整个向量,如果任何读取器线程在该向量内具有引用是非常危险的,因为在交换时,另一个向量很可能会被破坏,在这种情况下,来自读取器线程的任何引用都可能变得无效。

因此,每次您的读取器线程访问向量时,它们都需要一个锁。因此,使用交换在这里无济于事。它唯一可行的方法是通过使用某种多读取器 - 单写入器锁来确保没有读取器处于活动状态。

可能对您有用的是

std::vector<std::shared_ptr<bigdata_t>> shared_vec;

这样,您只需要正确同步指针交换并确保:

  • 启动读取器线程或
  • 您永远不会保留迭代器,并且对 Vector 的访问会正确同步。