我可以使用 std::vector::swap 修改共享向量吗?
Can I use std::vector::swap to modify a shared vector?
我正在开发多个线程读取访问单个 std::vector
大量(和大)数据的软件。
我对多个 thead 访问单个对象的复杂性有一些基本的了解,使用互斥量可以大大简化事情。
就我而言,修改现有对象比复制它要昂贵得多。所以我正在考虑创建一个副本,修改副本(同时不持有互斥锁)和
然后将其交换回共享对象。
我不能使用 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()
仅由单个线程调用,因此这基本上是单个 writer/multiple reader 方法。
它运行得非常快,但是将数据交换回共享向量有点像作弊。
我的问题是:
这种方法是否正确且线程安全?
假设你交换了整个向量,如果任何 reader 线程在该向量中有引用是非常危险的,因为在交换时,另一个向量很可能被破坏,在这种情况下任何引用来自reader 线程可能会失效。
因此,每次您的 reader 线程访问向量时,它们都需要一个锁。所以使用 swap 在这里无济于事。它唯一可行的方法是通过使用某种多重 reader - 单个写入器锁来确保没有 reader 处于活动状态。
可能适合您的是
std::vector<std::shared_ptr<bigdata_t>> shared_vec;
这样,您只需正确同步指针交换并确保:
- 一旦启动 reader 个线程或
,向量的大小就不会改变
- 您永远不会保留迭代器并且对 vector 的访问已正确同步。
我正在开发多个线程读取访问单个 std::vector
大量(和大)数据的软件。
我对多个 thead 访问单个对象的复杂性有一些基本的了解,使用互斥量可以大大简化事情。
就我而言,修改现有对象比复制它要昂贵得多。所以我正在考虑创建一个副本,修改副本(同时不持有互斥锁)和 然后将其交换回共享对象。
我不能使用 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()
仅由单个线程调用,因此这基本上是单个 writer/multiple reader 方法。
它运行得非常快,但是将数据交换回共享向量有点像作弊。
我的问题是:
这种方法是否正确且线程安全?
假设你交换了整个向量,如果任何 reader 线程在该向量中有引用是非常危险的,因为在交换时,另一个向量很可能被破坏,在这种情况下任何引用来自reader 线程可能会失效。
因此,每次您的 reader 线程访问向量时,它们都需要一个锁。所以使用 swap 在这里无济于事。它唯一可行的方法是通过使用某种多重 reader - 单个写入器锁来确保没有 reader 处于活动状态。
可能适合您的是
std::vector<std::shared_ptr<bigdata_t>> shared_vec;
这样,您只需正确同步指针交换并确保:
- 一旦启动 reader 个线程或 ,向量的大小就不会改变
- 您永远不会保留迭代器并且对 vector 的访问已正确同步。