我有许多对象,可能数量很大,这些对象正在并发写入。我想用互斥锁来保护对它们的访问。为此,我考虑使用std::vector<std::mutex>
,但是这不起作用,因为std::mutex
没有复制或移动构造函数,而std::vector::resize()
需要它们。
有什么推荐的解决方案吗?
编辑:
所有C++随机访问容器是否都需要重新调整大小的复制或移动构造函数?std::deque
是否有帮助?
再次编辑:
首先,感谢您的所有思考。我对避免使用互斥锁或将其移动到对象中(我不愿透露详细信息和原因)的解决方案不感兴趣。因此,考虑到我需要可调节数量的互斥锁(在没有互斥锁被锁定时保证进行调整),那么似乎有几种解决方案。
1 我可以使用固定数量的互斥锁,并使用哈希函数将对象映射到互斥锁上(如Captain Oblivous的答案)。这将导致冲突,但如果互斥锁的数量远大于线程数,但仍小于对象数,则冲突的数量应该很少。
2 我可以定义一个包装类(如ComicSansMS的答案),例如
struct mutex_wrapper : std::mutex
{
mutex_wrapper() = default;
mutex_wrapper(mutex_wrapper const&) noexcept : std::mutex() {}
bool operator==(mutex_wrapper const&other) noexcept { return this==&other; }
};
使用std::vector<mutex_wrapper>
来管理mutex(互斥锁)。
3 我可以使用std::unique_ptr<std::mutex>
来管理单个mutex(就像Matthias的答案中所示)。这种方法的问题在于每个mutex都是在堆上单独分配和释放的。因此,我更喜欢
4 std::unique_ptr<std::mutex[]> mutices( new std::mutex[n_mutex] );
当需要一定数量的mutices时,初始分配一定数量n_mutex
, 如果后来发现不足, 我只需简单地
if(need_mutex > n_mutex) {
mutices.reset( new std::mutex[need_mutex] );
n_mutex = need_mutex;
}
那么我应该使用这些中的哪一个呢(1、2、4)?
vector
只需要对象可移动,而对于resize
,它们需要是无抛出移动构造的。 - Kerrek SBcollection<std::atomic<T>>
来替代collection<T>
和collection<mutex>
以保护前者。 - Jerry Coffin