单例+多态+线程安全

一、综述

略;

二、开发环境

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;
}

四、参考

很多且乱也找不到了!

五、结果

以大家自己测试的为准;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值