有没有办法在C++中实现单例对象:
(我不太了解我的C++,但是在执行任何代码之前初始化积分和常量静态变量的情况(即,甚至在执行静态构造函数之前 - 它们的值可能已在程序中"初始化")如果是这样的话 - 也许这可以被利用来实现单例互斥体 - 这反过来可以用来保护真正的单例的创建......)
很好,现在我似乎有几个好的答案(羞耻我不能标记2或3作为答案).似乎有两个广泛的解决方案:
c++ singleton construction multithreading lazy-initialization
我有一个多线程C++应用程序,它使用OpenSceneGraph库进行3D渲染.我打算使用boost :: threads将OSG的渲染循环作为一个单独的线程,将包含共享状态的数据结构传递给线程.我试图避免任何太重量级(如互斥量)的同步,因为渲染循环需要非常紧,OSG本身试图避免必须锁定.大多数共享状态在线程启动之前设置,并且从不更改.我确实有一些需要更改的数据,我计划双重缓冲.但是,我有一个简单的布尔值来表示线程暂停渲染,然后恢复渲染,另一个杀死它.在这两种情况下,app线程都会设置bool,而渲染线程只会读取它.我是否需要同步访问这些bool?据我所知,可能发生的最糟糕的事情是渲染循环在暂停或退出之前继续进行额外的帧.
我一直在寻找SO和MSDN的答案来回答这个问题,但似乎无法找到明确的最终答案......
我知道它是在C++ 11标准中并且当前的GCC版本就是这样的,但VC2010目前是否保证了本地静态变量初始化的线程安全性?
即:这对VC2010有线程安全吗?
static S& getInstance()
{
static S instance;
return instance;
}
Run Code Online (Sandbox Code Playgroud)
...如果没有,目前使用VC2010在C++中获得线程安全的单例实现的最佳实践是什么?
编辑:正如Chris Betti的回答所指出的,VC2010没有实现本地静态变量init的线程安全性.
我在运行传给我的一些旧代码时遇到了一个问题.它可以在99%的时间内工作,但偶尔会发现它会抛出"违规读取位置"异常.我有可变数量的线程可能在整个过程的生命周期中执行此代码.低出现频率可能表示竞争条件,但我不知道为什么在这种情况下会导致异常.这是有问题的代码:
MyClass::Dostuff()
{
static map<char, int> mappedChars;
if (mappedChars.empty())
{
for (char c = '0'; c <= '9'; ++c)
{
mappedChars[c] = c - '0';
}
}
// More code here, but mappedChars in not changed.
}
Run Code Online (Sandbox Code Playgroud)
在第一次调用operator []时,在map的operator []实现中抛出异常(使用STL的VS2005实现.)
mapped_type& operator[](const key_type& _Keyval)
{
iterator _Where = this->lower_bound(_Keyval); //exception thrown on the first line
// More code here
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试在operator []中冻结线程并尝试让它们同时运行它,但是我无法使用该方法重现异常.
你能想出为什么会抛出这种情况,而且只有部分时间?
(是的,我知道STL不是线程安全的,我需要在这里进行更改.我很好奇为什么我看到上面描述的行为.)
根据要求,这里有一些关于异常的更多细节:
app15-51-02-0944_2008-10-23.mdmp中0x00639a1c(app.exe)的未处理异常:0xC0000005:访问冲突读取位置0x00000004.
感谢大家提出多线程问题的解决方案,但这不是这个问题要解决的问题.是的,我理解所呈现的代码没有得到正确的保护,并且在它试图完成的内容方面有些过分.我已经有了实现它的修复程序.我只是想更好地理解为什么要抛出这个异常.
c++ ×4
boolean ×1
c++11 ×1
construction ×1
exception ×1
mutex ×1
singleton ×1
stl ×1
visual-c++ ×1