安全有效的将互斥体放在容器条目上的方法 [英] Safe and effective way to put a mutex on a container entry
问题描述
C ++的 std :: mutex
没有移动构造函数。有一个很好的原因。基本上,移动构造函数本身通常不是线程安全的,并且互斥体的整个点是多个线程将尝试同时访问它。
C++'s std::mutex
does not have a move constructor. There is a good reason for that. Basically, move constructors themselves are not generally thread safe, and the whole point of a mutex is that multiple threads will be trying to access it simultaneously.
这是一个不幸的暗示是一个互斥体不能直接放入容器。容器需要能够安全地移动它们的内容,而且你不能用mutex来做。
An unfortunate implication of this is that a mutex cannot be placed into a container directly. Containers need the ability to safely move their contents around, and you can't do that with a mutex.
简单的方法是只使用一个单独互斥。但是,假设我想要更细粒度的控制呢?如果我通过一个容器实现一个数据库(例如: std :: map
),似乎合理的想要锁定个别记录,而不只是整个数据库。
The easy way out is to just protect the entire container with a single separate mutex. But suppose I want finer-grained control than that? If I'm implementing a database via a container (eg: std::map
), it seems reasonable to want the ability to lock individual records, not just the whole database.
接下来要记住的是使用 std :: unique_ptr
来解决问题。这将编译,但它并没有真正改变基本的问题,是吗?移动存在问题的情况是 thread1
使容器更改导致条目移动,而 thread2
位于使用该容器条目的中间。在这种情况下, thread2
可能很容易结束持有一个破坏的条目或智能指针。看起来不管是什么,你最终必须在执行任何操作之前用互斥体锁定整个容器。
The next thing that comes to mind is to hack around the problem by using std::unique_ptr
. That would compile, but it doesn't really change the basic problem, does it? The scenario where there's a problem with move is where thread1
makes a container change that causes an entry move while thread2
is in the middle of using that container entry. In this scenario, thread2
could just as easily end up holding a destructed entry or smart pointer. It seems like no matter what, you end up having to lock the entire container with a mutex before doing anything.
似乎应该有一个已知的成语
It seems like there ought to be a known idiom for doing these kinds of things.
推荐答案
互斥体不需要移动:
假设地图中的每一行都像:
Imagine that every row in your map is like:
template <class T>
class row
{
shared_ptr<mutex> m;
T data;
...
};
因此,如果您的行需要移动或复制,则没有问题。
So if your row need to be moved or copied, there is no problem.
然后,您可以从每个进程访问互斥体以访问数据。
Then, you may access the mutex from every process to access the data.
当然,您需要一个全局互斥体来执行在整个地图上的更改:insert / delete / [] /任何其他操作更改地图的状态。
Of course, you need a global mutex to perform changes on the whole map: insert / delete / [] / any other operation that change the state of the map.
已编辑:
按照一个简单的代码示例,每行都有一个互斥体。 (它不实现任何其他只是数据结构)
Following a simple example of code with a mutex in every row. (It does not implement anything else that just the data structure)
#include <memory>
#include <map>
#include <mutex>
template <class T>
class row
{
std::shared_ptr<std::mutex> m;
T data;
public:
row( std::shared_ptr<std::mutex> mut): m(mut){};
};
auto main () -> int
{
std::shared_ptr<std::mutex> mut(new std::mutex);
std::map<int,row<int>> db;
row<int> a(mut);
db.insert(std::pair<int, row<int>>(1, a));
return 0;
}
这篇关于安全有效的将互斥体放在容器条目上的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!