一、综述
略;
二、开发环境
win10+vs2019(v142);
三、测试代码
#include <string> #include <iostream> #include <thread> #include <mutex> using namespace std; void My_Thread_A1(size_t index, size_t count); void My_Thread_A2(size_t index, size_t count); //单例的实现以及单例的派生类对象实现 class Base { public: static Base* Get_Instance (int mode); static Base* Init_Instance(int mode); virtual uint32_t FuncTest() { return 0; } mutex m_in_mutex; uint32_t m_count = 0; //为了方便查看,public protected: Base() {} private: static Base* _instance; }; Base* Base::_instance = nullptr; class son1 : public Base { friend class Base; public: uint32_t FuncTest() { lock_guard<std::mutex> lock(m_in_mutex); m_count += 1; return m_count; } private: son1() {}; }; class son2 : public Base { friend class Base; public: uint32_t FuncTest() { m_count+=1; return m_count; } private: son2() {}; }; #pragma region 方式一 lock_guard mutex m_mutex;//线程互斥对象 Base* Base::Init_Instance(int mode) { //std::lock_guard<std::mutex> m(m_mutex);//放开此行此函数和用方式二调用注释掉此行的此函数效果同 if (_instance == nullptr) { if (mode == 1) { _instance = new son1(); } else if (mode == 2) { _instance = new son2(); } else { _instance = new Base(); } } return _instance; } #pragma endregion #pragma region 方式二call_once static std::once_flag s_flag; Base* Base::Get_Instance(int mode) { std::call_once(s_flag, Init_Instance,mode); return _instance; } #pragma endregion int main() { cout << "Hello world!" << endl; //单线程与多线程对比测试 //My_Thread_A1(); //My_Thread_A2(); //遇见过计数缺少的时候,待进一步测试 //std::thread t1(My_Thread_A1, 1, 200); //std::thread t2(My_Thread_A1, 2, 200); //t1.join(); //t2.join(); const int thrNum = 100; //新开线程数量 std::thread th[thrNum]; for (size_t i=0;i< thrNum;i++) { th[i] = std::thread(My_Thread_A1, i + 1, 1000); //th[i] = std::thread(My_Thread_A2, i + 1, 2000); //变量未加锁(出现计数不足的情况) } for (size_t i = 0; i < thrNum; i++) { th[i].join(); } cout << "************************************************" << endl; cout <<"最终的结果是:" << Base::Get_Instance(1)->m_count << endl; /* 经过简单的测试,两个地方缺少锁都会导致计数的不足; 所以要想实现线程安全的单例,首先需要在实例化对象的地方保证“单例”,同时也需要对“单例”中的资源 进行多线程的保护; */ cout << "************************************************" << endl; //Base* a = Base::Init_Instance(2); //a->FuncTest(); //两个子类共享一个m_count; //for (size_t i=0;i<10000;i++) //{ // cout<<Base::Init_Instance(1)->FuncTest() << endl; //} system("pause"); return 0; } void My_Thread_A1(size_t index,size_t count) { for (size_t i = 0; i < count; i++) { //cout << index << ":" << Base::Init_Instance(1)->FuncTest() << endl;//实例化单例对象未加锁(出现计数不足的情况) cout << index << ":" << Base::Get_Instance(1)->FuncTest() << endl; } cout << index << ":Finish---------------------------------------------------------" << endl; } void My_Thread_A2(size_t index, size_t count) { for (size_t i = 0; i < count; i++) { cout << index << ":" << Base::Init_Instance(2)->FuncTest() << endl; //cout << index << ":" << Base::Get_Instance(2)->FuncTest() << endl; } cout << "2:Finish---------------------------------------------------------" << endl; }
四、参考
很多且乱也找不到了!
五、结果
以大家自己测试的为准;