C++ 这种类型的编码是线程安全的还是死锁安全的?

C++ 这种类型的编码是线程安全的还是死锁安全的?,c++,boost,thread-safety,C++,Boost,Thread Safety,下面是数据容器。我们希望多个线程能够搜索容器并获取数据对象 #include <boost/thread.hpp> using boost::shared_ptr; using boost::mutex; using boost::lock_guard; using std::string; class CData { public: bool find(string& value, const string& fieldName) {

下面是数据容器。我们希望多个线程能够搜索容器并获取数据对象

#include <boost/thread.hpp>

using boost::shared_ptr;
using  boost::mutex;
using  boost::lock_guard;
using std::string;

class CData
{
public:
    bool find(string& value, const string& fieldName)
    {
        lock_guard<mutex> guard(m_lock);
        auto it=m_data.find(fieldName);
        if( it!=m_data.end())
        {
            value=it->second;
            return true;
        }
        return false;
    }


    CData(const CData& rhs)
    {
        lock_guard<mutex> guard(rhs.m_lock);
        m_data=rhs.m_data;
    }

    CData& operator=( const CData& rhs ) 
    {
       if ( this == &rhs ) 
       {
           return *this; 
       }

       mutex* lock1;
       mutex* lock2;

       if(this<&rhs)
       {
           lock1=&m_lock;
           lock2=&rhs.m_lock;
       }
       else
       {
           lock1=&rhs.m_lock;
           lock2=&m_lock;
       }

       lock_guard<mutex> guard1(*lock1);
       lock_guard<mutex> guard2(*lock2);

       m_data=rhs.m_data;
    }



private:

    std::map<string,string> m_data;
    mutable mutex m_lock;
};
#包括
使用boost::shared\u ptr;
使用boost::mutex;
使用boost::lock_-guard;
使用std::string;
班级CData
{
公众:
布尔查找(字符串和值、常量字符串和字段名)
{
锁紧防护罩(m锁);
auto it=m_data.find(字段名);
if(it!=m_data.end())
{
值=它->秒;
返回true;
}
返回false;
}
CData(常数CData和rhs)
{
锁护板(右侧m锁);
m_数据=rhs.m_数据;
}
CData和运算符=(常量CData和rhs)
{
如果(此==&rhs)
{
归还*这个;
}
互斥锁*lock1;
互斥锁*lock2;
如果(这一秒);
返回true;
}
返回false;
}
私人:
CDATA容器()
}
互斥锁;
标准::映射m_键2数据;
};

也许吧,但是,使用所有这些互斥锁可能没有那么有效。如果我能建议一个小的修改:

class CData
{
public:
    void insert(const string& key, const shared_ptr<CData>& data) const;
    ...
private:
    const std::map<string,string> m_data;
};
Edit2:此外,CDATA容器::实例中的同步在中是不必要的,现在可以完全安全地执行以下操作:

CDataContainer& instance()
{
    static CDataContainer s_instance;
    return s_instance;
}

这个问题可能属于codereview(至少我听说过)

对于
CData::operator=()
,您可能可以通过执行以下操作来避免有关锁顺序或地址比较的问题:

CData& operator=( CData tmp ) 
{
    lock_guard<mutex> guard(m_lock); 
    m_data=std::move(tmp.m_data);
}
CData&operator=(CData tmp)
{
锁紧防护罩(m锁);
m_数据=标准::移动(tmp.m_数据);
}
我认为它更简单、更清晰,并且我怀疑是否有任何显著的性能影响。除了奇怪的自我分配情况,它仍然可以正常工作,但需要一些锁,并且不必要地复制
m_数据


您可能还需要定义移动复制和分配成员。

对于初学者,请注意,
p0
仅在
p0
p1
是同一数组对象的一部分时定义。否则行为未定义。您可以使用
std::less()(p0,p1)
,即使
p0
p1
不是同一个数组的一部分,也定义了此操作。使用地址来确保锁定顺序是有创意的,但您可能不想尝试实现自己的STL类型并发版本。这可能是一个更好的帖子。好的,明白了。我必须使用唯一的id对于每个CData,这应该不会太难。如果你看他的类,他不会插入其中。如果他确实需要该功能,那么仍然可以更新,同时保持不变性和线程安全性,正如我引用的链接所示。但是你有一个
insert
成员函数。你打算复制
find
CData的成员函数
?我忘了在CData中添加一个成员函数。这是一个合并成员函数,将修改CData中的数据。我仍然不需要互斥锁。我将查看您的链接。我的全部目标是避免复制CData,因为目前我有一个复制CData的结构这就是我发现的瓶颈。我现在能给你的最实际的建议是使用类似的方法,而不是尝试推出你自己的解决方案。如果不知道很多细节,很难给出一个好的答案,但是如果合并只是偶尔发生,复制也不是那么令人望而却步,那么你可能只需要一个简单的复制就可以成功和交换实现,同时保持数据常量。
CDataContainer& instance()
{
    static CDataContainer s_instance;
    return s_instance;
}
CData& operator=( CData tmp ) 
{
    lock_guard<mutex> guard(m_lock); 
    m_data=std::move(tmp.m_data);
}