1

我正在阅读Mir 项目源代码,偶然发现了这段代码:

void mir::frontend::ResourceCache::free_resource(google::protobuf::Message* key)
{
    std::shared_ptr<void> value;
    {
        std::lock_guard<std::mutex> lock(guard);

        auto const& p = resources.find(key);

        if (p != resources.end())
        {
            value = p->second;
        }

        resources.erase(key);
    }
}

我以前在其他项目中也看到过这一点。它在擦除之前保存对映射中值的引用,即使该块受到 lock_guard 保护。我不确定他们为什么使用std::shared_ptr value来引用该值。

如果我们删除value = p->second会有什么影响?

有人请赐教吗?

这是代码http://bazaar.launchpad.net/~mir-team/mir/trunk/view/head:/src/frontend/resource_cache.cpp

4

2 回答 2

3

我猜这是为了避免value在锁定代码中运行析构函数。这个锁是为了保护对映射的修改,并且运行一些任意代码,例如锁定另一个对象的析构函数,是不需要也不需要的。

试想一下,value无论出于何种原因,间接访问映射的析构函数,或另一个线程共享结构。您有可能最终陷入僵局。

底线是:从锁定的代码中运行尽可能少的代码,但不能更少。并且永远不要从锁定的代码中调用外部的、未知的函数(例如shared_ptr删除器或回调)。

于 2013-03-11T16:59:59.403 回答
2

目标是将删除器的实际执行移动shared_ptr到释放锁之后。这样,如果删除器(或使用默认删除器的析构函数)需要很长时间,则不会为该操作持有锁。

如果您要删除value = p->second,则在持有锁时该值将被销毁。由于锁保护地图,但不保护实际值,因此它持有锁的时间会超过严格必要的时间。

于 2013-03-11T17:00:20.413 回答