C++ multi-Ithread访问无序映射的运行时错误
我有一段多线程代码,它试图使用stlC++ multi-Ithread访问无序映射的运行时错误,c++,multithreading,singleton,C++,Multithreading,Singleton,我有一段多线程代码,它试图使用stlunordered_map创建一个线程本地单例对象 这是你的电话号码。我在这里逐字复制代码: #include <iostream> #include <unordered_map> #include <vector> #include <thread> #include <algorithm> #include <mutex> using namespace std; class si
unordered_map
创建一个线程本地单例对象
这是你的电话号码。我在这里逐字复制代码:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <thread>
#include <algorithm>
#include <mutex>
using namespace std;
class single
{
public:
// Every thread needs to call this to get its individual instance
static single* getInstance( unsigned int threadId );
static void print( unsigned int threadId )
{
std::cout << "threadId:" << threadId << ", Singleton: " << _instances[threadId] << std::endl;
}
protected:
// Made protected not private so that singleton can be subclassed
single(); // Clients cant construct objects directly
~single(); // cannot be destroyed by clients
single(const single &) = delete; // non-copyable
single& operator=(const single &) = delete; // can't be copy assigned
single(single &&) = delete; // non-move constructible
single & operator=(single && ) = delete; // non-move assignable
private:
static std::unordered_map<unsigned,single*> _instances;
static std::mutex _lock;
};
std::mutex single::_lock;
std::unordered_map<unsigned,single*> single::_instances;
single::single(){}
single::~single(){}
single* single::getInstance( unsigned int threadId )
{
if( _instances.count( threadId ) == 0 )
{
std::lock_guard<std::mutex> lg(_lock);
if( _instances.count( threadId ) == 0 )
{
_instances[threadId] = new single;
std::cout <<"Created By ThreadId: " << threadId <<std::endl;
}
}
return _instances[threadId];
}
void Run( unsigned int threadId )
{
single::getInstance(threadId)->print(threadId);
}
int main()
{
std::vector<std::thread> workers;
const unsigned threadCount = 16;
for( auto i = 0; i != threadCount; ++i )
{
workers.push_back( std::thread( Run, i ) );
}
for_each( workers.begin(), workers.end(), std::mem_fn(&thread::join) );
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
单班
{
公众:
//每个线程都需要调用它来获取其单独的实例
静态单*getInstance(无符号int-threadId);
静态无效打印(无符号int-threadId)
{
标准::cout
有谁能解释一下,在这段代码的哪一部分发生了竞争情况
不,它不是线程安全的。一旦至少有一个写入程序,所有访问都需要由锁进行保护。因此,第一个\u instances.count()
没有保护,可能会导致数据争用
…如果这个解决方案可以用于线程本地单例
您可以使用它来控制本地线程存储持续时间
您还可以在对无序地图
进行任何访问之前,将锁防护装置迁移到
single* single::getInstance( unsigned int threadId )
{
std::lock_guard<std::mutex> lg(_lock);
if( _instances.count( threadId ) == 0 )
{
_instances[threadId] = new single;
std::cout <<"Created By ThreadId: " << threadId <<std::endl;
}
return _instances[threadId];
}
single*single::getInstance(unsigned int-threadId)
{
标准:锁紧装置lg(锁紧装置);
if(_instances.count(threadId)==0)
{
_实例[threadId]=新的单个实例;
std::cout well,我提到了count()是一个常量函数。它不是线程安全的,因为它只读取并且不修改映射状态吗?const
意味着count()
函数不会更改容器的内容,并不意味着其他函数不会同时更改内容(数据竞争)。关于您的代码迁移建议,我最初是这样做的。但它不起作用。因此我认为我应该尝试使用双重检查锁定来防止_instances.count()上的争用条件所以,据我所知,基本上线程x使用计数读取和线程y写入容器之间存在竞争?是的,这是正确的。它在这里工作;您是否链接到pthread(不确定为什么它之前不工作)?