• 单例模式


    使用场景

    需要全进程唯一实例时,往往会使用单例模式进行设计

    唯一数据入口

    假设一个对象负责更改本地设置,例如配置服务的网络端口号。如果出现两个或多个线程,每个线程拥有一个实例,线程并发共同进行配置。每个实例都在修改端口号。最终修改的结果就是不可控的。

    共用的资源

    现在我们假设有一个数据队列,由三个数据的生产者向队列push数据,一个消费者处理三个不同来源的数据。对队列进行pop操作。这就可能会涉及到四个线程并发的处理。怎样让这四个线程都能够获得到这个队列进行操作?全局变量?nonono不够优雅,这时候,使用单例模式。一个唯一的队列实例。不可以由其他对象创建,整个进程唯一,线程就能够通过这一唯一的实例进行数据的交互。

    唯一的控制者

    很多时候,我们需要对进程内的资源进行合理的调控,例如服务端进程在某一时刻,突然又大量数据或客户端请求进来。我们需要动态的增加数据处理线程,启用其他闲置的资源等等。这一时刻,决策者只能有一个。如果两个实例分别调控,最终的结果一定不是我们期望的。

    实现

    单例的实现有两种方式:懒汉、饿汉

    懒汉方式

    突出一个懒字。意思是只有在使用的时候才去实例化对象。以时间换空间,当访问量较小的时候,可以使用这种方式

    为了保证线程安全,一般采用双检锁方法来创建对象

    #include <iostream>
    #include <pthread.h>
    
    
    using namespace std;
    
    
    class CLog
    {
    public:
        static CLog * getInstance();
    
    private:
        CLog(){}
        CLog(const CLog & o) = delete;
        CLog & operator=(const CLog & o) = delete;
    
    private:
        static CLog * instance_;
        static pthread_mutex_t mutex_;
    };
    
    CLog * CLog::instance_ = nullptr;
    pthread_mutex_t CLog::mutex_ = PTHREAD_MUTEX_INITIALIZER;
    
    CLog * CLog::getInstance()
    {
        if (instance_ == nullptr)
        {
            pthread_mutex_lock(&mutex_);
            if (instance_ == nullptr)
            {
                // instance_ = new CLog(); 可能在执行new的过程中,对象的初始化还没有完成,但是instance_就不是nullptr了,这可能导致另外一个线程使用了未完全初始化的instance_,为避免这种情况,使用下面的方法
                CLog * tmp = new CLog();
                instance_ = tmp;
            }
            pthread_mutex_unlock(&mutex_);
        }
    
        return instance_;
    }
    
    int main()
    {
        CLog * log = CLog::getInstance();
    
        return 0;
    }

    饿汉模式

    对象还没有使用的时候就已经创建好了。这样以空间换时间

    饿汉模式是线程安全的,因为不存在多线程实例化的问题

    #include <iostream>
    
    
    class CLog
    {
    public:
        static CLog * getInstance();
    
    private:
        CLog() = default;
        ~CLog() = default;
        CLog(const CLog & o) = delete;
        CLog & operator=(const CLog & o) = delete;
    
    private:
        static CLog * instance_;
    };
    
    CLog * CLog::instance_ = new CLog();
    
    CLog * CLog::getInstance()
    {
        return instance_;
    }
    
    
    int main()
    {
        CLog * log = CLog::getInstance();
    
        return 0;
    }
  • 相关阅读:
    Oracle EXP
    Using Spring in Web and WinForms
    System.ComponentModel(未完...)
    工作必须得到强势方的支持!
    book.Save()还是bookManager.Save(book)?
    C#中常用的Attribute搜集(刚开始...)
    领域模型是否能够屏蔽数据库?
    合格代码的最基本的标准
    关于配置系统的设计
    对象分类
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/10277951.html
Copyright © 2020-2023  润新知