我如何使用 std::vector<std::mutex> 之类的东西?

How can I use something like std::vectorlt;std::mutexgt;?(我如何使用 std::vectorlt;std::mutexgt; 之类的东西?)

本文介绍了我如何使用 std::vector<std::mutex> 之类的东西?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有大量但可能不同的对象同时写入.我想用互斥锁保护该访问.为此,我以为我使用了 std::vector,但这不起作用,因为 std::mutex 没有副本或移动构造函数,而 std::vector::resize() 需要.

I have a large, but potentially varying, number of objects which are concurrently written into. I want to protect that access with mutexes. To that end, I thought I use a std::vector<std::mutex>, but this doesn't work, since std::mutex has no copy or move constructor, while std::vector::resize() requires that.

这个难题的推荐解决方案是什么?

What is the recommended solution to this conundrum?

编辑:所有 C++ 随机访问容器都需要复制或移动构造函数来重新调整大小吗?std::deque 有帮助吗?

edit: Do all C++ random-access containers require copy or move constructors for re-sizing? Would std::deque help?

再次编辑

首先,感谢您的所有想法.我对避免静音和/或将它们移动到对象中的解决方案不感兴趣(我不提供细节/原因).所以考虑到我想要一个可调整数量的互斥锁(在没有互斥锁被锁定的情况下保证发生调整)的问题,那么似乎有几种解决方案.

First, thanks for all your thoughts. I'm not interested in solutions that avoid mutices and/or move them into the objects (I refrain from giving details/reasons). So given the problem that I want a adjustable number of mutices (where the adjustment is guaranteed to occur when no mutex is locked), then there appear to be several solutions.

1 我可以使用固定数量的 mutic,并使用哈希函数从对象映射到 mutic(如 Oblivous 船长的回答).这样会产生冲突,但是如果mutices的数量远大于线程的数量,但仍然小于对象的数量,那么冲突的数量应该很小.

1 I could use a fixed number of mutices and use a hash-function to map from objects to mutices (as in Captain Oblivous's answer). This will result in collisions, but the number of collisions should be small if the number of mutices is much larger than the number of threads, but still smaller than the number of objects.

2 我可以定义一个包装类(如 ComicSansMS 的回答),例如

2 I could define a wrapper class (as in ComicSansMS's answer), e.g.

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.

3 我可以使用 std::unique_ptr<std::mutex> 来管理单个互斥锁(如 Matthias 的回答).这种方法的问题是每个互斥体都是在堆上单独分配和取消分配的.因此,我更喜欢

3 I could use std::unique_ptr<std::mutex> to manage individual mutexes (as in Matthias's answer). The problem with this approach is that each mutex is individually allocated and de-allocated on the heap. Therefore, I prefer

4 std::unique_ptrmutices( 新 std::mutex[n_mutex] );

当初始分配一定数量的 n_mutex mutices 时.如果以后发现这个数字不够,我干脆

when a certain number n_mutex of mutices is allocated initially. Should this number later be found insufficient, I simply

if(need_mutex > n_mutex) {
  mutices.reset( new std::mutex[need_mutex] );
  n_mutex = need_mutex;
}

那么我应该使用这些 (1,2,4) 中的哪一个?

So which of these (1,2,4) should I use?

推荐答案

vector 要求值是可移动的,以便随着值的增长保持连续的值数组.您可以创建一个包含互斥体的向量,但您无法执行任何可能需要调整其大小的操作.

vector requires that the values are movable, in order to maintain a contiguous array of values as it grows. You could create a vector containing mutexes, but you couldn't do anything that might need to resize it.

其他容器没有这个要求;deque[forward_]list 应该可以工作,只要您在构建过程中或使用 emplace() 就地构建互斥锁或 resize().insert()push_back() 等函数将不起作用.

Other containers don't have that requirement; either deque or [forward_]list should work, as long as you construct the mutexes in place either during construction, or by using emplace() or resize(). Functions such as insert() and push_back() will not work.

或者,您可以添加额外的间接级别并存储unique_ptr;但是您在另一个答案中的评论表明您认为动态分配的额外成本是不可接受的.

Alternatively, you could add an extra level of indirection and store unique_ptr; but your comment in another answer indicates that you believe the extra cost of dynamic allocation to be unacceptable.

这篇关于我如何使用 std::vector&lt;std::mutex&gt; 之类的东西?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:我如何使用 std::vector&lt;std::mutex&gt; 之类的东西?

基础教程推荐