C++ 使用boost shared_互斥锁时出现死锁
当我将C++ 使用boost shared_互斥锁时出现死锁,c++,multithreading,boost,C++,Multithreading,Boost,当我将shared\u ptr与自定义Deleter和boost::shared\u mutex一起使用时,我有一个非常微妙的死锁错误: 首先,有一个WorkManager类来管理工作对象: class Work; class WorkManager { public: static WorkManager& instance() { static WorkManager instance; return instance; } s
shared\u ptr
与自定义Deleter
和boost::shared\u mutex
一起使用时,我有一个非常微妙的死锁错误:
首先,有一个WorkManager类来管理工作对象:
class Work;
class WorkManager {
public:
static WorkManager& instance() {
static WorkManager instance;
return instance;
}
std::shared_ptr<Work> get(int id);
std::shared_ptr<Work> create(int id);
void update(unsigned int diff);
private:
void _remove(int id, Work* t);
WorkManager();
mutable boost::shared_mutex _mutex;
std::map<int, std::weak_ptr<Work>> _works;
};
void WorkManager::_remove(int id, Work* t)
{
BOOST_ASSERT(t);
std::lock_guard<boost::shared_mutex> lock(_mutex);
_works.erase(id);
delete t;
}
std::shared_ptr<Work> WorkManager::get(int id) {
boost::shared_lock<boost::shared_mutex> lock(_mutex);
auto iter = _works.find(id);
if(iter == _works.end())
return nullptr;
return iter->second.lock();
}
std::shared_ptr<Work> WorkManager::create(int id) {
Work* t = new Work(id);
std::shared_ptr<Work> res;
res.reset(t, std::bind(&WorkManager::_remove, this, t->id(), std::placeholders::_1));
std::lock_guard<boost::shared_mutex> lock(_mutex);
_works[res->id()] = res;
return res;
}
void WorkManager::update(unsigned int diff) {
boost::shared_lock<boost::shared_mutex> lock(_mutex);
for(auto& t : _works)
{
if(std::shared_ptr<Work> work = t.second.lock())
work->update(diff);
}
}
如何解决这个问题?我想解决办法是:
std::vector<std::shared_ptr<Work>> tmp;
{
boost::shared_lock<boost::shared_mutex> lock(_mutex);
for(auto& t : _works)
{
if(std::shared_ptr<Work> w = t.second.lock())
{
w->do_something();
tmp.push_back(w); //prevent w destroy before the read lock unlock
}
}
}
std::vector-tmp;
{
boost::共享锁(互斥锁);
适用于(自动和测试:_工程)
{
if(std::shared_ptr w=t.second.lock())
{
w->dou_某事();
tmp.push_back(w);//在读取锁解锁之前防止w销毁
}
}
}
但是,如果有人忘记了这个技巧,这很容易出错。您的
\u删除(int-id,Work*t)
会从映射中删除元素id
,也会删除t
。为什么要在一个调用中组合这些不相关的东西?\u remove由shared\u ptr的析构函数调用,所以它需要做两件事:1。删除它管理的指针。2.从WorkManager的std::Map中删除弱_ptr您在这里实际想要实现什么?WorkManager::create(int)
的目的(前置和后置条件)是什么?顺便说一句,如果您能清理语言(语法)并在文本中使用代码高亮显示,这将非常有帮助。创建仅用于显示共享的\u ptr自定义删除器用法您在这里执行多线程的方式被认为是容易出错的(正如您刚刚发现的)和过时的。现代的方式是消息传递,而不是数据共享。你的高级问题是什么?
std::vector<std::shared_ptr<Work>> tmp;
{
boost::shared_lock<boost::shared_mutex> lock(_mutex);
for(auto& t : _works)
{
if(std::shared_ptr<Work> w = t.second.lock())
{
w->do_something();
tmp.push_back(w); //prevent w destroy before the read lock unlock
}
}
}