线安全的静态变量没有mutexing?
-
20-08-2019 - |
题
我记得阅读,静态声明的变量在内的方法是不线的安全。(见 什么关于Meyer是单身? 如前所述通过 托德*加德纳)
Dog* MyClass::BadMethod()
{
static Dog dog("Lassie");
return &dog;
}
我的图书馆产生C++编码最终用户汇编的一部分,他们的应用程序。代码生成需要初始化静态变量的在线安全的跨平台的方式。我想用 boost::call_once
以互斥的变初始化,但随后最终用户受到提高依赖性。
有没有办法为我做这个不强迫的额外依赖于最终用户?
解决方案
你是正确的,静态的初始化喜欢,是不是线的安全(在这里, 是一篇文章讨论什么的编译器会把它变成)
目前,没有标准、线的安全,便携式方法的初始化静单身.双检查锁定可以使用,但是你需要的潜在的非便携式的线图书馆(见的讨论 在这里,).
这里有几个选择,如果线安全是一个必须:
- 不要偷懒(载):初始化过静的初始化。这可能是一个问题,如果另一个静态的电话这功能在它的构造,由于以静态的初始化是不确定的(见 在这里,).
- 使用提升(如你所说)或者洛基
- 滚你的 自己单独对你的支持的平台 (可能应该避免的除非 你是一个线程专家)
- 锁定一个互斥的每一次你需要的访问。这可能是非常缓慢。
例为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 库内部使用此的一些实施例中,虽然我不能吨记住哪些组件在这个时候。