我有一个类似于以下内容的属性:
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 ++的新手。
答案 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()
时,实例将被初始化,并且线程安全。