Xce*_*ity 17 c++ singleton static multithreading c++11
我在C++中实现了单例(静态版本).我知道关于这种模式和潜在的线程安全问题的所有争议,但我很好奇为什么这个确切的实现不会停止.该程序永不退出,最终仍处于死锁状态.
singleton.h:
#pragma once
#include <thread>
#include <atomic>
class Singleton
{
public:
static Singleton& getInstance();
private:
std::thread mThread;
std::atomic_bool mRun;
Singleton();
~Singleton();
void threadFoo();
};
Run Code Online (Sandbox Code Playgroud)
singleton.cpp
#include "singleton.h"
Singleton& Singleton::getInstance()
{
static Singleton instance;
return instance;
}
Singleton::Singleton()
{
mRun.store(true);
mThread = std::thread(&Singleton::threadFoo, this);
}
Singleton::~Singleton()
{
mRun.store(false);
if(mThread.joinable())
mThread.join();
}
void Singleton::threadFoo()
{
while(mRun)
{
}
}
Run Code Online (Sandbox Code Playgroud)
main.cpp中
#include "singleton.h"
int main()
{
Singleton::getInstance();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我所知道的:
使用Visual Studio 2012.感谢您的建议.
Bit*_*tex 22
在主线程上,main()
终止后,CRT获取退出锁并调用静态实例析构函数,等待后台线程退出.
在后台线程上,在线程函数终止后,CRT尝试获取退出锁以执行一些线程终止工作.这会永远阻塞,因为退出锁是由主线程保持的,它正在等待该线程退出.
这是由CRT实现引起的简单死锁.最重要的是,您不能在Windows上的静态实例析构函数中等待线程终止.
我把它追溯到void __cdecl _lock(int locknum)
里面mlock.c
.当main()
结束时,主线程去那里并进入临界区EnterCriticalSection( _locktable[locknum].lock );
.然后调用Singleton析构函数,另一个线程尝试进入相同的临界区,但不能,因此它开始等待主线程离开临界区.反过来,主线程等待另一个线程.所以我猜这是一个错误.
好的,谢谢大家的提示。显然,这种模式的实现会导致 VC++ 上的死锁。
经过进一步的研究,我发现这个实现基于 C++11 机制,可在 VC++ 中运行。
单例.h
#pragma once
#include <thread>
#include <atomic>
#include <memory>
#include <mutex>
class Singleton
{
public:
static Singleton& getInstance();
virtual ~Singleton();
private:
static std::unique_ptr<Singleton> mInstance;
static std::once_flag mOnceFlag;
std::thread mThread;
std::atomic_bool mRun;
Singleton();
void threadFoo();
};
Run Code Online (Sandbox Code Playgroud)
单例.cpp
#include "singleton.h"
std::unique_ptr<Singleton> Singleton::mInstance = nullptr;
std::once_flag Singleton::mOnceFlag;
Singleton& Singleton::getInstance()
{
std::call_once(mOnceFlag, [] { mInstance.reset(new Singleton); });
return *mInstance.get();
}
Singleton::Singleton()
{
mRun.store(true);
mThread = std::thread(&Singleton::threadFoo, this);
}
Singleton::~Singleton()
{
mRun.store(false);
if(mThread.joinable())
mThread.join();
}
void Singleton::threadFoo()
{
while(mRun.load())
{
}
}
Run Code Online (Sandbox Code Playgroud)
更新
看来微软已经意识到这个问题了。在 VC++ 论坛中,名为“dlafleur”的用户报告了此帖子: https ://connect.microsoft.com/VisualStudio/feedback/details/747145
归档时间: |
|
查看次数: |
2663 次 |
最近记录: |