我记得阅读,静态声明的变量在内的方法是不线的安全。(见 什么关于Meyer是单身? 如前所述通过 托德*加德纳)

Dog* MyClass::BadMethod()
{
  static Dog dog("Lassie");
  return &dog;
}

我的图书馆产生C++编码最终用户汇编的一部分,他们的应用程序。代码生成需要初始化静态变量的在线安全的跨平台的方式。我想用 boost::call_once 以互斥的变初始化,但随后最终用户受到提高依赖性。

有没有办法为我做这个不强迫的额外依赖于最终用户?

有帮助吗?

解决方案

你是正确的,静态的初始化喜欢,是不是线的安全(在这里, 是一篇文章讨论什么的编译器会把它变成)

目前,没有标准、线的安全,便携式方法的初始化静单身.双检查锁定可以使用,但是你需要的潜在的非便携式的线图书馆(见的讨论 在这里,).

这里有几个选择,如果线安全是一个必须:

  1. 不要偷懒(载):初始化过静的初始化。这可能是一个问题,如果另一个静态的电话这功能在它的构造,由于以静态的初始化是不确定的(见 在这里,).
  2. 使用提升(如你所说)或者洛基
  3. 滚你的 自己单独对你的支持的平台 (可能应该避免的除非 你是一个线程专家)
  4. 锁定一个互斥的每一次你需要的访问。这可能是非常缓慢。

例为1:

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

Dog* MyClass::BadMethod()
{
  return &dog;
}

例为4:

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

其他提示

不知道这是否是你的意思还是没有什么,但你可以通过调用pthread_once而不是取消对POSIX系统升压依赖。我猜你必须做一些事情上的Windows不同,但避免正是为什么升压在首位一个线程库,以及为什么人们支付取决于它的价格。

做什么“线程安全”的固有约束与您的线程实现。你必须依靠的的东西的,即使它只是依赖于平台的内存模型。这只不过是不以纯的C ++ 03能够在所有假设有关线程,这是语言的范围以外的任何东西。

你能做到这一点的一种方式,它不需要线程安全互斥是使单文件静态的,而不是静态的功能:

static Dog dog("Lassie");
Dog* MyClass::BadMethod()
{
  return &dog;
}

Dog实例将主线程运行之前被初始化。文件静态变量有初始化为了一个著名的问题,但只要狗不依赖于另一个转换单元中定义的任何其他静态,这不应该成为关注的问题。

我知道的,确保您不会有像你"static Dog"非保护资源的线程问题的唯一方法是让一个要求,即他们都实例化的 的创建任何线程之前

这可能是因为刚刚记录,他们有做任何事情之前调用主线程MyInit()功能一样简单。然后,你构造MyInit()实例化和破坏包含这些静力学的每种类型的一个一个对象。

唯一的其他选择是把另一种限制性他们如何可以使用所生成的代码(使用升压,Win32的螺纹等)。无论这些解决方案都是在我看来可以接受的 - 它的好来生成规则,他们必须遵守

如果他们不遵守载列由你的文档的规则,那么所有的赌注都关闭。他们必须调用初始化函数或依赖于加速的规则是没有道理给我。

据我所知,只有这个时间已经安全完成,没有互斥体或全局实例的初始化之前是马修·威尔森的 < EM>不完善C ++ ,该讨论如何使用 “自旋mutex” 来做到这一点。我不靠近我对它的副本,所以不能在这个时候任何更精确地告诉你。

IIRC,还有 STLSoft 库内部使用此的一些实施例中,虽然我不能吨记住哪些组件在这个时候。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top