在额外范围内包括std :: lock_guard

Kab*_*ode 28 c++ mutex locking

做一些事情是否有意义,例如放入一个std::lock_guard额外的范围,以便锁定时间尽可能短?

伪代码:

// all used variables beside the lock_guard are created and initialized somewhere else
...// do something

{ // open new scope
    std::lock_guard<std::mutex> lock(mut);
    shared_var = newValue;  
} // close the scope

... // do some other stuff (that might take longer)
Run Code Online (Sandbox Code Playgroud)

除了锁定持续时间短之外还有其他优点吗?

什么可能是负面影响?

Rei*_*ica 26

是的,将锁定防护装置的范围限制为尽可能短,但不能更短,这当然是有道理的.

持有锁的时间越长,线程越有可能阻止等待锁,这会影响性能,因此通常被认为是一件坏事.

但是,您必须确保程序仍然正确,并且必须始终保持锁定,即访问或修改受锁保护的共享资源时.

可能还有一点需要考虑(我在这里没有足够的实践经验来确定).锁定/释放互斥锁可能本身就是一项具有重要性能成本的操作.因此,可能会发现,在一次操作过程中保持锁定的时间稍长,而不是解锁和重新锁定它可以实际上提高整体性能.这是分析可以告诉你的东西.


L. *_* F. 12

可能存在一个缺点:您无法以这种方式保护初始化.例如:

{
    std::lock_guard<std::mutex> lock(mut);
    Some_resource var{shared_var};
} // oops! var is lost
Run Code Online (Sandbox Code Playgroud)

你必须使用这样的作业:

Some_resource var;
{
    std::lock_guard<std::mutex> lock(mut);
    var = shared_Var;
}
Run Code Online (Sandbox Code Playgroud)

你知道,这可能不是那么好,因为对于某些类型,虚拟初始化(我故意避免使用术语"默认初始化")然后分配比直接初始化效率低.(我故意避免使用术语"直接初始化")此外,在某些情况下,您无法在初始化后更改变量.(例如const)


@P我指出了这个解决方案:

// use an immediately-invoked temporary lambda
Some_resource var {
    [&] {
        std::lock_guard<std::mutex> lock(mut);
        return shared_var;
    } () // parentheses for invoke
};
Run Code Online (Sandbox Code Playgroud)

通过这种方式,几乎所有流行的现代编译器都能很好地实现返回值优化,并且从C++ 17开始强制实施,您可以完全按照预期进行操作.

  • 你可以使用立即调用的lambda (3认同)
  • `some_resource var {[&](){std :: lock_guard <std :: mutex> lock(mut); return shared_var; }()};` (2认同)