C ++返回函数lock_guard

时间:2017-09-25 08:12:43

标签: c++ multithreading c++11

我拥有包含在shared_ptr中的资源“resource”,我想从其他线程访问它。 当我这样做时:

// foo.h
class Foo{
public:
    std::shared_ptr<Setup> GetSomeThing();
    void SetSomeThing();
private:
    std::shared_ptr<Setup> resource;
    std::mutex lock;
}
//Foo.cpp
std::shared_ptr<Setup> Foo::GetSomeThing()
{
    std::lock_guard<std::mutex> lock (mutex);
    return resource;
}

void Foo::SetSomeThing()
{
     std::lock_guard<std::mutex> lock (mutex);
     resource = ...;
}

一切都好吗? 什么时候会创建一个返回对象,何时会被锁定?它在文档中是否存在某些内容? 谢谢!

1 个答案:

答案 0 :(得分:1)

这个答案假定(为清楚起见)两行:

std::lock_guard<std::mutex> lock (mutex);

都替换为

std::lock_guard<std::mutex> guard (lock);

如果多个线程在没有同步的情况下访问std::shared_ptr<>的单个实例,并且其中任何一个调用非const成员,则会发生数据争用。

这意味着您必须确保SetSomeThing()GetSomething()之间的同步。

在提议的方式中引入std::mutex并使用std::lock_guard<>即可。返回的副本将在调用guard的析构函数之前构建。

请注意,它是关于同一个实例的。 GetSomeThing()返回的副本具有足够的内部同步,以确保无需同步其他实例即可访问(非const甚至破坏)。

但是,这些都不会阻止Setup拥有的任何共享std::shared_ptr<Setup>对象(部分)上的数据争用。如果对Setup的所有访问都是只读的,则多个线程可以访问它,但如果任何线程写入共享数据,则会发生数据争用(没有进一步同步,问题中没有显示)。

在启动多个线程之前,可以构造和初始化简单应用程序中的Setup之类的对象,并在除主线程之外的所有线程终止时进行破坏。在那种特定情况下,不需要进一步的同步,甚至提供的锁也是多余的。

这是一个非规范性的参考:

http://en.cppreference.com/w/cpp/memory/shared_ptr

请参阅开场说明的最后一段。

脚注:更改应用程序“设置”可能比仅仅确保属性上不会发生数据争用要困难得多。线程可能需要采用变更或“放弃”活动。例如,考虑一个图形程序,其中在“绘制”步骤期间改变屏幕分辨率。它应该完成绘制并生成一个太大/太小的画布,还是倾倒部分绘制的画布并采用新的分辨率?设置是否以这样的方式获得,即抽奖将产生与“之前”或“之后”一致的东西,而不是一些荒谬的(可能是崩溃的)混合体?