单例模式线程安全

今天我也来讲讲单例模式的实现,单例模式有很多种实现方式,像饿汉,懒汉,饿汉变种,懒汉变种等等。我这边就只介绍两种方式,一种动态创建,一种静态创建。

动态创建,很多人也把它叫做懒汉式的变种在变种,因为它是一种线程安全的,并且用时才创建的,相比静态创建它启动快些。
.h

#ifndef LAZYSINGLETON_H
#define LAZYSINGLETON_H

#include 

class LazySingleton
{
public:
    static LazySingleton* getinstance();
    void testfunc();
    void setval(int index);
private:
    LazySingleton();
    static QMutex m_mutex;
    static LazySingleton* m_pInstance;
    int m_index;
};

#endif // LAZYSINGLETON_H

.cpp

#include "lazysingleton.h"
#include 

QMutex LazySingleton::m_mutex;
LazySingleton* LazySingleton::m_pInstance = NULL;

LazySingleton::LazySingleton()
{
    m_index = 0;
}

LazySingleton *LazySingleton::getinstance()
{
//如果只是锁定+一次检查,则每次调用都要加锁,大大降低了性能;
//如果只是一次检查+锁定,则会出现并发条件。
    if (m_pInstance == NULL)
    {
        m_mutex.lock();
        if (m_pInstance == NULL)
            m_pInstance = new LazySingleton();
        m_mutex.unlock();
    }
    return m_pInstance;
}

void LazySingleton::testfunc()
{
    qWarning()<<"动态单例测试,也可以认为是线程安全的懒汉式";
}

void LazySingleton::setval(int index)
{
    m_index=m_index+index;
    qWarning()<<"动态单例测试,也可以认为是线程安全的懒汉式:"<<m_index;
}

静态创建,很多人也把它叫做饿汉式的变种,我认为它也是一种线程安全的,很多人说多线程情况下,它也会出现并发创建静态实例对象,但是我不这么认为,当然我可能没理解,有知道的麻烦解答一下。
.h

#ifndef HUNGRYSINGLETON_H
#define HUNGRYSINGLETON_H


class HungrySingleton
{
public:
    static HungrySingleton* getinstance();
    void testfunc();
    void setval(int index);
private:
    HungrySingleton();
    int m_index;
};

#endif // HUNGRYSINGLETON_H

#include "hungrysingleton.h"
#include 


HungrySingleton::HungrySingleton()
{
    m_index = 0;
}

HungrySingleton *HungrySingleton::getinstance()
{
    static HungrySingleton m_pInstance;
    return &m_pInstance;
}

void HungrySingleton::testfunc()
{
    qWarning()<<"静态单例测试,也可以认为是线程安全的饿汉式";
}

void HungrySingleton::setval(int index)
{
    m_index = m_index+index;
    qWarning()<<"静态单例测试,也可以认为是线程安全的饿汉式:"<<m_index;
}

测试:
.h

#ifndef WIDGET_H
#define WIDGET_H

#include 


class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void slottestLazySingleton();
    void slottestHungrySingleton();
    void slottestLazySingletonval1();
    void slottestLazySingletonval2();
    void slottestHungrySingletonval1();
    void slottestHungrySingletonval2();
private:
    QPushButton* m_lazybtn;
    QPushButton* m_lazysetvalbtn1;
    QPushButton* m_lazysetvalbtn2;
    QPushButton* m_hungrybtn;
    QPushButton* m_hungrysetvalbtn1;
    QPushButton* m_hungrysetvalbtn2;
};

#endif // WIDGET_H

.cpp

#include "widget.h"
#include "lazysingleton.h"
#include "hungrysingleton.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{

    m_lazybtn = new QPushButton("动态单例",this);
    m_lazysetvalbtn1 = new QPushButton("1-动态单例值加1",this);
    m_lazysetvalbtn2 = new QPushButton("2-动态单例值加1",this);
    m_hungrybtn = new QPushButton("静态单例",this);
    m_hungrysetvalbtn1 = new QPushButton("1-静态单例值加1",this);
    m_hungrysetvalbtn2 = new QPushButton("2-静态单例值加1",this);

    QVBoxLayout* lay = new QVBoxLayout;
    lay->addWidget(m_lazybtn);
    lay->addWidget(m_lazysetvalbtn1);
    lay->addWidget(m_lazysetvalbtn2);
    lay->addWidget(m_hungrybtn);
    lay->addWidget(m_hungrysetvalbtn1);
    lay->addWidget(m_hungrysetvalbtn2);
    this->setLayout(lay);

    connect(m_lazybtn,SIGNAL(clicked()),this,SLOT(slottestLazySingleton()));
    connect(m_lazysetvalbtn1,SIGNAL(clicked()),this,SLOT(slottestLazySingletonval1()));
    connect(m_lazysetvalbtn2,SIGNAL(clicked()),this,SLOT(slottestLazySingletonval2()));
    connect(m_hungrybtn,SIGNAL(clicked()),this,SLOT(slottestHungrySingleton()));
    connect(m_hungrysetvalbtn1,SIGNAL(clicked()),this,SLOT(slottestHungrySingletonval1()));
    connect(m_hungrysetvalbtn2,SIGNAL(clicked()),this,SLOT(slottestHungrySingletonval2()));
}

Widget::~Widget()
{
}

void Widget::slottestLazySingleton()
{
    LazySingleton::getinstance()->testfunc();
}

void Widget::slottestLazySingletonval1()
{
    LazySingleton::getinstance()->setval(1);
}

void Widget::slottestLazySingletonval2()
{
    LazySingleton::getinstance()->setval(1);
}

void Widget::slottestHungrySingleton()
{
    HungrySingleton::getinstance()->testfunc();
}

void Widget::slottestHungrySingletonval1()
{
    HungrySingleton::getinstance()->setval(1);
}

void Widget::slottestHungrySingletonval2()
{
    HungrySingleton::getinstance()->setval(1);
}

单例模式线程安全_第1张图片
单例模式线程安全_第2张图片

你可能感兴趣的:(QT,c/c++,qt,c++)