我如何使用类似std :: vector< std :: mutex>之类的东西? [英] How can I use something like std::vector<std::mutex>?

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

问题描述

我有大量但可能会变化的对象,这些对象会同时写入.我想使用互斥锁来保护该访问.为此,我以为我使用了std::vector<std::mutex>,但这是行不通的,因为std::mutex没有复制或移动构造函数,而std::vector::resize()却需要复制或移动构造函数.

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

修改: 所有C ++随机访问容器是否都需要复制或移动构造函数来调整大小? std :: deque是否会提供帮助?

再次编辑

首先,感谢您的所有想法.我对避免使用mutices和/或将其移动到对象中的解决方案不感兴趣(我不提供详细信息/原因).因此,考虑到我想要可调数量的mutices(保证在没有互斥锁被锁定时进行调整)的问题,那么似乎有几种解决方案.

1 我可以使用固定数量的mutices,并使用哈希函数将对象映射到mutices(就像上尉船长的回答一样).这将导致冲突,但是如果mutices的数量远大于线程的数量,但仍小于对象的数量,则冲突的数量应该少.

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>.

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

4 std::unique_ptr<std::mutex[]> mutices( new std::mutex[n_mutex] );

当最初分配一定数量的n_mutex的mutices时.如果以后发现这个数字不够用,我只是

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

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

解决方案

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

其他容器没有此要求;只要在构造过程中或使用emplace()resize()来构造互斥锁,deque[forward_]list都应该起作用. insert()push_back()之类的功能将不起作用.

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

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?

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

edit again

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 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 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; }
};

and use a std::vector<mutex_wrapper>.

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_ptr<std::mutex[]> mutices( new std::mutex[n_mutex] );

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;
}

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

解决方案

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.

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.

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;之类的东西?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆