单例模式线程安全

85 篇文章 1 订阅

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

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

#ifndef LAZYSINGLETON_H
#define LAZYSINGLETON_H

#include <QMutex>

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 <QDebug>

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 <QDebug>


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 <QtWidgets>


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

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值