线程安全的静态变量没有静音?

Gil*_*ili 13 c++ boost initialization thread-safety c++03

我记得读过在方法中声明的静态变量不是线程安全的.(请参阅托德加德纳提到的梅耶的单身人士怎么样)

Dog* MyClass::BadMethod()
{
  static Dog dog("Lassie");
  return &dog;
}
Run Code Online (Sandbox Code Playgroud)

我的库为最终用户生成C++代码,以便作为其应用程序的一部分进行编译.它生成的代码需要以线程安全的跨平台方式初始化静态变量.我想使用boost::call_once互斥变量初始化,但最后用户会暴露于Boost依赖项.

有没有办法让我这样做而不强迫最终用户有额外的依赖?

Tod*_*ner 10

你是正确的,这样的静态初始化不是线程安全的(这里有一篇讨论编译器将其转化为什么的文章)

目前,没有标准的,线程安全的,可移植的方式来初始化静态单例.可以使用双重检查锁定,但您需要潜在的非可移植线程库(请参阅此处的讨论).

如果线程安全是必须的,这里有几个选项:

  1. 不要懒惰(加载):在静态初始化期间初始化.如果另一个静态在其构造函数中调用此函数,则可能会出现问题,因为静态初始化的顺序未定义(请参见此处).
  2. 使用boost(如你所说)或Loki
  3. 在您支持的平台上滚动您自己的单例(除非您是线程专家,否则应该避免使用)
  4. 每次需要访问时锁定互斥锁.这可能非常慢.

示例1:

// in a cpp:
namespace {
    Dog dog("Lassie");
}

Dog* MyClass::BadMethod()
{
  return &dog;
}
Run Code Online (Sandbox Code Playgroud)

4的例子:

Dog* MyClass::BadMethod()
{
  static scoped_ptr<Dog> pdog;
  {
     Lock l(Mutex);
     if(!pdog.get())
       pdog.reset(new Dog("Lassie"));
  }
  return pdog.get();
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案现在已经过时了:http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11 (7认同)