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