将互斥锁置于容器条目上的安全有效方法

时间:2014-12-03 16:17:07

标签: c++ multithreading c++11 stl

C ++的std::mutex没有移动构造函数。有一个good reason for that。基本上,移动构造函数本身通常不是线程安全的,并且互斥体的全部意义在于多个线程将尝试同时访问它。

不幸的是,互斥锁不能直接放入容器中。容器需要能够安全地移动其内容,而您无法使用互斥锁。

简单的方法是用一个单独的互斥锁保护整个容器。但是假设我想要比那更精细的控制?如果我通过容器实现数据库(例如:std::map),那么希望能够锁定单个记录而不仅仅是整个数据库似乎是合理的。

我想到的下一件事就是使用std::unique_ptr解决问题。那会编译,但它并没有真正改变基本问题,是吗?移动存在问题的情况是thread1进行容器更改导致条目移动而thread2正在使用该容器条目。在这种情况下,thread2可能很容易最终持有被破坏的条目或智能指针。似乎无论如何,你最终都必须在做任何事情之前使用互斥锁来锁定整个容器。

似乎应该有一种已知的习惯用于做这些事情。

1 个答案:

答案 0 :(得分:1)

互斥锁不需要移动:

想象一下,地图中的每一行都是:

template <class T>
class row
{
    shared_ptr<mutex> m;
    T data;
    ...
};

因此,如果需要移动或复制行,则没有问题。

然后,您可以从每个进程访问互斥锁以访问数据。

当然,您需要一个全局互斥锁来对整个地图执行更改:insert / delete / [] /任何其他更改地图状态的操作。

编辑:

遵循每行中带有互斥锁的代码的简单示例。 (它没有实现只有数据结构的任何其他内容)

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