Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;:同时避免静态初始化顺序问题和竞争条件 我遇到了一个C++静态初始化命令问题,我用众所周知的“第一次使用构造”来解决:_C++_Winapi - Fatal编程技术网

C++;:同时避免静态初始化顺序问题和竞争条件 我遇到了一个C++静态初始化命令问题,我用众所周知的“第一次使用构造”来解决:

C++;:同时避免静态初始化顺序问题和竞争条件 我遇到了一个C++静态初始化命令问题,我用众所周知的“第一次使用构造”来解决:,c++,winapi,C++,Winapi,然而,我一直在四处搜索,似乎Windows(我的平台)并不能保证本地静态的线程安全,尽管它确实保证了全局静态的线程安全 所以,如果我使我的对象成为全局的,我会得到线程安全性,但我有初始化顺序问题。如果我使用“第一次使用时构造”,我可以避免初始化顺序问题,但我会得到竞争条件。如何同时解决这两个问题? < P>不要使用全局变量,也不要使用单体,并且不会有这些问题。在C++ 2011中,< < /P> < P>使用 STD::CalqIn()/: #包括 无效初始化(Foo*&ptr) { ptr=新

然而,我一直在四处搜索,似乎Windows(我的平台)并不能保证本地静态的线程安全,尽管它确实保证了全局静态的线程安全


所以,如果我使我的对象成为全局的,我会得到线程安全性,但我有初始化顺序问题。如果我使用“第一次使用时构造”,我可以避免初始化顺序问题,但我会得到竞争条件。如何同时解决这两个问题?

< P>不要使用全局变量,也不要使用单体,并且不会有这些问题。在C++ 2011中,< < /P> < P>使用<代码> STD::CalqIn()/<代码>:

#包括
无效初始化(Foo*&ptr)
{
ptr=新的Foo();
}
std::once_标志
Foo&Foo()
{
静态Foo*ptr(0);
std::call_一次(标记、初始化、std::ref(ptr));
返回*ptr;
}
如果您不能使用C++2011,您可能需要查看系统的底层功能。对于POSIX,这将是
pthread\u once()
。这是如何在其他平台上完成的,我不知道


也就是说,我建议不要使用它,因为它本质上是某种形式的全球数据,通常没有很好的理由使用它。也有例外,但很少见。实际上,这种情况非常罕见。

在windows上,您可以使用关键部分。这只允许一个线程在构造“lock”之后、在其解构之前(即在foo初始化之后、函数返回之前)在代码段中运行

#include <atlbase.h>

CComAutoCriticalSection fooCs;

Foo& GetFoo()
{
   CComCritSecLock<CComAutoCriticalSection> lock(cs);
   static Foo foo;
   return foo;
}
#包括
中国食品标准化委员会;
Foo&GetFoo()
{
CComCritSecLock锁(cs);
静态Foo-Foo;
返回foo;
}

顺便说一句,您可以通过执行
静态Foo-Foo来避免使用
new
(如果可以,您应该这样做);返回foo
如果你至少可以升级到Vista,你可以使用一次性初始化:。@MSN我没有说是,我只是说他应该在可能的情况下避免堆分配错误检查:你真的在编写多线程程序吗?如果没有,就不需要担心线程安全。或者,一种解决方案是让主线程在创建任何其他线程之前创建所有您想要的全局对象。要添加Scott所说的内容,您可以让
main
在创建线程之前调用一次返回
static
变量的所有函数来初始化对象。回答得好。但是您可以添加更多关于如何正确操作的描述。我创建的全局对象是用于流输出的。它是适当的全局性的。如果您确定它需要是全局性的,并且它与iostreams相关,那么您可能应该做iostreams本身所做的事情,这在这里简要讨论:。或者只是看看你的特定平台上std::cout和friends的实现——然后做他们所做的。哇,我不知道
call\u once
+1我不确定这项措施的实施范围有多广。在他们进入标准之前,参加委员会会议并听取他们的意见是有帮助的!我用的是VC++2008;C++2011不是我的选择。很抱歉,我不是Windows爱好者,所以我不知道什么是
pthread\u once()
。现在,fooCs有一个初始化顺序问题。如果fooCs是静态文件,则没有初始化顺序问题。无论如何,请使用DCLP(www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf)。
#include <mutex>
void initialize(Foo*& ptr)
{
    ptr = new Foo();
}
std::once_flag flag
Foo& foo()
{
    static Foo* ptr(0);
    std::call_once(flag, initialize, std::ref(ptr));
    return *ptr;
}
#include <atlbase.h>

CComAutoCriticalSection fooCs;

Foo& GetFoo()
{
   CComCritSecLock<CComAutoCriticalSection> lock(cs);
   static Foo foo;
   return foo;
}