使用boost时出现死锁shared_mutex

时间:2017-06-20 13:21:52

标签: c++ multithreading boost

当我使用自定义shared_ptrDeleter的{​​{1}}时,我有一个非常微妙的死锁错误:

首先有一个WorkManager类来管理Work对象:

boost::share_mutex

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); } } 由定时器触发,以100ms的固定间隔调用。由于WorkManager::update()不包含WorkManager而只包含shared_ptr<Work>,因此在weak_ptr<Work>返回后,work->update(diff);可能会被销毁,因为可能没有work持有这个特别的shared_ptr<Work>了。然后,work将通过WorkManager::_remove()的自定义删除工具进行调用。请注意,更新线程已经保持读锁定,在shared_ptr<Work>中,它需要获取写锁定。但是,它必须在获取此写锁之前释放读锁。所以这个线程已经死了。

这个问题意味着我无法编写任何管理器的功能,例如:

_remove()

如何解决这个问题?我找到了一个解决方案:

boost::shared_lock<boost::shared_mutex> lock(_mutex);
for(auto& t : _works)
{
    if(std::shared_ptr<Work> w = t.second.lock())
        w->do_something();    
}

然而,如果有人忘记了这个技巧,这很容易出错。

0 个答案:

没有答案