Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用boost shared_互斥锁时出现死锁_C++_Multithreading_Boost - Fatal编程技术网

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