1

我有一个位于多线程应用程序中的资源存储对象。为了(希望)确保线程安全,我每次想要访问资源或插入新资源时都会锁定一个互斥锁。例如,插入一个新资源:

void ResourceManager::insertResource(const std::string& id)
{
    // create the object with such ID
    Resource res = Resource(id);

    // ... more code on res

    // lock the mutex to insert the resource
    std::lock_guard<std::mutex> guard(mResourcesMutex);

    // insert the resource in a STL container
    mResources.insert(ResourceContainer::value_type(id, res));

    // ... more code that does not require the mutex lock
}

我希望 lock_guard 的范围最小,以便尽快调用它的析构函数,并且其他线程可以访问资源。特别是,我想在 mResources.insert(...) 语句之后解锁互斥锁。

我考虑过使用简单的 if 语句来确定 lock_guard 的范围:

    if(true)
    {
        std::lock_guard<std::mutex> guard(mResourceMutex);
        mResources.insert(ResourceContainer::value_type(id, res);
    }

但我不知道它是否有效。我发现很难检查这是否正确地确定了 lock_guard 的范围,或者另一方面,编译器是否只是认为我疯了,并且它优化了去掉 if 语句的代码。

我的问题是:

  • 这管用吗?
  • 这值得么?我会注意到性能下降吗?
  • 有没有更好的选择?
4

2 回答 2

6
  • 是的,它有效。一旦您退出作用域,该作用域的本地对象将立即被销毁。

  • 是的,这是值得的,尤其是在像您的示例这样的情况下(减少对象的生命周期以确保尽早释放资源 - 但您也可以使用它来缩小临时标识符的范围并使其在此之后无法访问,即使这种用法比您的示例更有趣)。

  • 是的,有一个(稍微)更好的选择:只使用没有if子句的大括号:

.

{
    std::lock_guard<std::mutex> guard(mResourceMutex);
    mResources.insert(ResourceContainer::value_type(id, res);
}

适当的编译器将能够优化生成的代码,if (true)因此生成的代码将是相同的,但从样式的角度来看,单独的大括号要干净得多。此外,单独的大括号是一个众所周知且立即可识别的习语,而你if (true)的不是并且让读者想知道(即使是短暂的)“ if的目的是什么?哦等等,对,这是通常的范围限制习语。 …… ”。

于 2013-04-24T09:47:35.250 回答
5

你为什么用if(true)?你可以简单地使用block scope

{
    std::lock_guard<std::mutex> guard(mResourceMutex);
    mResources.insert(ResourceContainer::value_type(id, res);
}
于 2013-04-24T09:48:12.393 回答