当前位置: 首页 > news >正文

甘南网站设计公司广州网站建设推广专家

甘南网站设计公司,广州网站建设推广专家,河北石家庄疫情,网站推广优化哪家公司好定义 保证一个类仅有一个实例,并提供一个该实例的全局访问点。 应用场景 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器,提供一种…

定义

保证一个类仅有一个实例,并提供一个该实例的全局访问点。

应用场景

  • 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
  • 如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
  • 这应该是类设计者的责任,而不是使用者的责任。

结构

在这里插入图片描述

代码示例

普通懒汉式(线程不安全)

多线程情况下线程不安全

//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H///  普通懒汉式实现 -- 线程不安全 //
#include <iostream> // std::cout
#include <mutex>    // std::mutex
#include <pthread.h> // pthread_create
class SingleInstance
{public:// 获取单例对象static SingleInstance *GetInstance();// 释放单例,进程退出时调用static void deleteInstance();// 打印单例地址void Print();private:// 将其构造和析构成为私有的, 禁止外部构造和析构SingleInstance();~SingleInstance();// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值SingleInstance(const SingleInstance &signal);const SingleInstance &operator=(const SingleInstance &signal);private:// 唯一单例对象指针static SingleInstance *m_SingleInstance;
};//初始化静态成员变量
SingleInstance *SingleInstance::m_SingleInstance = NULL;SingleInstance* SingleInstance::GetInstance()
{if (m_SingleInstance == NULL){m_SingleInstance = new (std::nothrow) SingleInstance;  // 没有加锁是线程不安全的,当线程并发时会创建多个实例}return m_SingleInstance;
}void SingleInstance::deleteInstance()
{if (m_SingleInstance){delete m_SingleInstance;m_SingleInstance = NULL;}
}void SingleInstance::Print()
{std::cout << "我的实例内存地址是:" << this << std::endl;
}SingleInstance::SingleInstance()
{std::cout << "构造函数" << std::endl;
}SingleInstance::~SingleInstance()
{std::cout << "析构函数" << std::endl;
}
///  普通懒汉式实现 -- 线程不安全  //// 线程函数
void *PrintHello(void *threadid)
{// 主线程与子线程分离,两者相互不干涉,子线程结束同时子线程的资源自动回收pthread_detach(pthread_self());// 对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取int tid = *((int *)threadid);std::cout << "Hi, 我是线程 ID:[" << tid << "]" << std::endl;// 打印实例地址SingleInstance::GetInstance()->Print();pthread_exit(NULL);
}#endif
//test.cpp
/****************************************************/
#include "Singleton.h"
#include <pthread.h> // pthread_create
#define NUM_THREADS 5 // 线程个数
int main()
{pthread_t threads[NUM_THREADS] = {0};int indexes[NUM_THREADS] = {0}; // 用数组来保存i的值int ret = 0;int i = 0;std::cout << "main() : 开始 ... " << std::endl;for (i = 0; i < NUM_THREADS; i++){std::cout << "main() : 创建线程:[" << i << "]" << std::endl;indexes[i] = i; //先保存i的值// 传入的时候必须强制转换为void* 类型,即无类型指针ret = pthread_create(&threads[i], NULL, PrintHello, (void *)&(indexes[i]));if (ret){std::cout << "Error:无法创建线程," << ret << std::endl;exit(-1);}}// 手动释放单实例的资源SingleInstance::deleteInstance();std::cout << "main() : 结束! " << std::endl;return 0;
}

加锁懒汉式(线程安全)

//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H
#include <pthread.h> // pthread_create
#include <iostream> // std::cout
#include <mutex>    // std::mutex
///  加锁的懒汉式实现  //
class SingleInstance
{public:// 获取单实例对象static SingleInstance *&GetInstance();//释放单实例,进程退出时调用static void deleteInstance();// 打印实例地址void Print();private:// 将其构造和析构成为私有的, 禁止外部构造和析构SingleInstance();~SingleInstance();// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值SingleInstance(const SingleInstance &signal);const SingleInstance &operator=(const SingleInstance &signal);private:// 唯一单实例对象指针static SingleInstance *m_SingleInstance;static std::mutex m_Mutex;
};//初始化静态成员变量
SingleInstance *SingleInstance::m_SingleInstance = NULL;
std::mutex SingleInstance::m_Mutex;SingleInstance *&SingleInstance::GetInstance()
{//  这里使用了两个 if判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁,//  避免每次调用 GetInstance的方法都加锁,锁的开销毕竟还是有点大的。if (m_SingleInstance == NULL) {std::unique_lock<std::mutex> lock(m_Mutex); // 加锁if (m_SingleInstance == NULL){m_SingleInstance = new (std::nothrow) SingleInstance;}}return m_SingleInstance;
}void SingleInstance::deleteInstance()
{std::unique_lock<std::mutex> lock(m_Mutex); // 加锁if (m_SingleInstance){delete m_SingleInstance;m_SingleInstance = NULL;}
}void SingleInstance::Print()
{std::cout << "我的实例内存地址是:" << this << std::endl;
}SingleInstance::SingleInstance()
{std::cout << "构造函数" << std::endl;
}SingleInstance::~SingleInstance()
{std::cout << "析构函数" << std::endl;
}
///  加锁的懒汉式实现  //#endif

静态局部变量的懒汉单例(C++11线程安全)

//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H
#include <pthread.h> // pthread_create
#include <iostream> // std::cout
#include <mutex>    // std::mutex
///  内部静态变量的懒汉实现  //
class Single
{public:// 获取单实例对象static Single &GetInstance();// 打印实例地址void Print();private:// 禁止外部构造Single();// 禁止外部析构~Single();// 禁止外部复制构造Single(const Single &signal);// 禁止外部赋值操作const Single &operator=(const Single &signal);
};Single &Single::GetInstance()
{// 局部静态特性的方式实现单实例static Single signal;return signal;
}void Single::Print()
{std::cout << "我的实例内存地址是:" << this << std::endl;
}Single::Single()
{std::cout << "构造函数" << std::endl;
}Single::~Single()
{std::cout << "析构函数" << std::endl;
}
///  内部静态变量的懒汉实现  //#endif

饿汉式(本身就线程安全)

//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H
#include <pthread.h> // pthread_create
#include <iostream> // std::cout
#include <mutex>    // std::mutex
// 饿汉实现 /
class Singleton
{
public:// 获取单实例static Singleton* GetInstance();// 释放单实例,进程退出时调用static void deleteInstance();// 打印实例地址void Print();private:// 将其构造和析构成为私有的, 禁止外部构造和析构Singleton();~Singleton();// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值Singleton(const Singleton &signal);const Singleton &operator=(const Singleton &signal);private:// 唯一单实例对象指针static Singleton *g_pSingleton;
};// 代码一运行就初始化创建实例 ,本身就线程安全
Singleton* Singleton::g_pSingleton = new (std::nothrow) Singleton;Singleton* Singleton::GetInstance()
{return g_pSingleton;
}void Singleton::deleteInstance()
{if (g_pSingleton){delete g_pSingleton;g_pSingleton = NULL;}
}void Singleton::Print()
{std::cout << "我的实例内存地址是:" << this << std::endl;
}Singleton::Singleton()
{std::cout << "构造函数" << std::endl;
}Singleton::~Singleton()
{std::cout << "析构函数" << std::endl;
}
// 饿汉实现 /#endif

代码参考:C++ 线程安全的单例模式总结
我这里运行结果总是有点不尽人意,不知道是怎么回事,所以就没放运行结果,推荐看原文。

要点总结

  • Singleton模式中的实例构造器可以设置为protected以允许子类派生。
  • Singleton模式一般不要支持拷贝构造函数和Clone接口,因为这有可能导致多个对象实例,与Singleton模式的初衷违背。
  • 如何实现多线程环境下安全的Singleton?注意对双检查锁的正确实现。
http://www.ds6.com.cn/news/19563.html

相关文章:

  • 网站建设入驻网络推广网络营销外包
  • 网站怎么做404页面百度网站推广价格
  • 怎么自己设计房子效果图网站优化包括哪些内容
  • 郑州做网站公司网络推广企划
  • 宁波网站建设设计网站建站在线制作
  • 淘宝客手机网站开发对网站外部的搜索引擎优化
  • 怎么建一个网站卖东西奉化云优化seo
  • 网站开发国内外研究动态网络开发
  • 中国建设招标网是私人网站吗软文范例大全500字
  • 网站开发电话话术网站推广优化的方法
  • 新手做电商需要多少钱搜索引擎优化seo优惠
  • 软件开发项目管理文档海南快速seo排名优化
  • 免费做淘客cms网站seo的内容怎么优化
  • 织梦做的网站网速打开慢是怎么回事推荐seo关键词优化
  • 商城网站建设教程品牌策划推广方案
  • 多网合一网站平台建设中国推广网
  • 樟木头镇网站建设公司php搭建一个简单的网站
  • 网站怎么做按钮关键词挖掘工具免费
  • 影视网站建设目的网站seo优化价格
  • 网站查询域名ip查询市场推广计划方案
  • 巴西有做amazon网站吗流氓网站
  • 网站建设免费空间注册导航长春网长春关键词排名站设计
  • 章丘做网站哪家强如何推广网上国网
  • 网站做聚合页面方案如何写百度推广技巧方法
  • 福田网站开发谷歌推广代理公司
  • 如何在网站上做标注网络推广的话术怎么说
  • 做美女网站赚钱吗无锡营销型网站制作
  • 岳阳网站建设联系方式浙江网络科技有限公司
  • 网站前端是做啥的下载百度导航app
  • 网站备案注册广州seo网络培训课程