Wal*_*ter 25 c++ multithreading mutex vector c++11
我有一个很大但可能变化的对象,它们被同时写入.我想用互斥锁保护访问权限.为此,我认为我使用了一个std::vector<std::mutex>,但这不起作用,因为std::mutex没有复制或移动构造函数,同时std::vector::resize()需要.
这个难题的推荐解决方案是什么?
编辑:所有C++随机访问容器是否需要复制或移动构造函数来重新调整大小?std :: deque会帮助吗?
再次编辑
首先,感谢您的所有想法.我对避免突变和/或将它们移动到对象中的解决方案不感兴趣(我不提供细节/原因).因此,考虑到我想要一个可调数量的mutices(在没有锁定互斥锁时保证调整的情况)的问题,那么似乎有几种解决方案.
1我可以使用固定数量的mutices并使用哈希函数从对象映射到mutices(如Oblivous上尉的答案).这将导致冲突,但如果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; }
};
Run Code Online (Sandbox Code Playgroud)
并使用一个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;
}
Run Code Online (Sandbox Code Playgroud)
那么我应该使用这些(1,2,4)中的哪一个?
Mik*_*our 13
vector要求值是可移动的,以便在增长时保持连续的值数组.您可以创建包含互斥锁的向量,但是您无法执行任何可能需要调整其大小的操作.
其他容器没有这个要求; 只要您在构造期间或使用或构建互斥锁,就可以使用deque或者[forward_]list应该工作.诸如和不起作用的功能.emplace()resize()insert()push_back()
或者,您可以添加额外级别的间接和存储unique_ptr; 但是您在另一个答案中的评论表明您认为动态分配的额外成本是不可接受的.
Mat*_*ard 12
你可以用std::unique_ptr<std::mutex>而不是std::mutex. unique_ptrs是可移动的.
小智 9
如果要创建一定长度:
std::vector<std::mutex> mutexes;
...
size_t count = 4;
std::vector<std::mutex> list(count);
mutexes.swap(list);
Run Code Online (Sandbox Code Playgroud)
我建议使用固定的互斥池。保留一个固定数组,std::mutex并根据对象的地址选择要锁定的数组,就像使用哈希表一样。
std::array<std::mutex, 32> mutexes;
std::mutex &m = mutexes[hashof(objectPtr) % mutexes.size()];
m.lock();
Run Code Online (Sandbox Code Playgroud)
该hashof函数可以是简单的函数,将指针值移动几个位。这样,您只需初始化互斥体一次,就可以避免调整向量大小的副本。
| 归档时间: |
|
| 查看次数: |
17377 次 |
| 最近记录: |