zoukankan      html  css  js  c++  java
  • 单例模式

    使用场景

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

    唯一数据入口

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

    共用的资源

    现在我们假设有一个数据队列,由三个数据的生产者向队列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;
    }
  • 相关阅读:
    HandlerExceptionResolver 实现全局异常捕获
    Cocoapods安装过程
    mysql 安装
    崩溃日志的字段简单说明
    简述static关键字、void与void *(void指针)、函数指针
    在python后台如何将客户端提交的form表单数据提取出来?
    iOS如何提高页面流畅度
    屏幕显示机制
    计算机网络体系小知识
    Protobuf java版本安装步骤
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/10277951.html
Copyright © 2011-2022 走看看