C ++线程安全延迟加载

时间:2012-11-02 15:52:57

标签: c++ multithreading lazy-loading

我有一个类似于以下内容的属性:

private:
Foo* myFoo_m;

public:
Foo getMyFoo() const
{
    if (myFoo_m == NULL)
    {
       myFoo_m = new Foo();
       // perform initialization

这在单线程环境中运行良好,但如何在多线程环境中处理?我发现的大部分信息都涉及静态单例,但在这种情况下,myFoo是一个公共实例属性。

我正在从C#(我可以使用Lazy)和Java(我可以使用双重检查锁定)移植它,但似乎没有一种直接的方法在C ++中执行此操作。 我不能依赖任何外部库(没有BOOST),这需要在Windows和Linux上工作。我也不能使用C ++ 11。

任何见解都会很好。我是C ++的新手。

3 个答案:

答案 0 :(得分:5)

如果您有权访问 c ++ 11 ,则可以使用std::mutex来阻止多个线程初始化延迟部分。 (注意:std::mutex仅在具有VS2012的Windows上可用)

您甚至可以使用std::lock_guard

执行互斥锁的范围检索
private:

std::mutex m_init_mutex;

public:

Foo getMyFoo() const
{
    {
       std::lock_guard<std::mutex> lock(m_init_mutex);
       if (myFoo_m == NULL)
       {
          myFoo_m = new Foo();
          // perform initialization
       }
    }

编辑:OP现在声称C ++ 11不是一个选项,但也许这个答案将来会有用

答案 1 :(得分:4)

通过说“没有C ++ 11”,“没有Boost或其他第三方代码”,“必须在Windows和Linux上运行”,你限制自己使用特定于实现的锁定机制。

我认为你最好的选择是为自己定义一个简单的锁类,并实现它在Linux上使用pthread_mutex和在Windows上使用CriticalSection。可能你已经有一些特定于平台的代码,首先启动线程。

您可以尝试使用Windows Services for UNIX来避免编写特定于平台的代码,但对于一个锁定它可能不值得。虽然它是由微软提供的,但无论如何你可能认为它是一个外部库。

答案 2 :(得分:1)

警告:我没有看到“没有C ++ 11”的要求,所以请忽略答案。


由于C ++ 11强制要求静态变量初始化是线程安全的,所以这里有一种简单的方法可以考虑“作弊”:

Foo init_foo()
{
    // initialize and return a Foo
}

Foo & get_instance_lazily()
{
    static Foo impl = init_foo();
    return impl;
}

第一次调用get_instance_lazily()时,实例将被初始化,并且线程安全。