c++:自己动手实现线程安全的c++单例类
前段时间使用c++做项目开发,需要根据根据配置文件路径加载全局配置文件,并对外提供唯一访问点。面对这样一个需求,自然的就想到了使用单例模式来创建一个单例配置对象,供外部调用。一开始想使用boost中自带的单例类来实现,但是遗憾的是,boost中的的单例类好像只能使用无参的类构造函数,而我希望将配置文件路径作为单例配置对象的构造函数参数,此外正好借此机会使用c++自己动手实现一个单例类。
1.线程安全的c++单例类
实现线程安全的c++单例类,主要要实现以下几点:1)构造函数私有化,即构造函数、拷贝构造函数和复制构造函数定义为private。构造函数私有化是为了防止在类外部定义类对象;拷贝构造函数私有化是为了防止拷贝行为产生多个实例;复制构造函数私有化,防止赋值产生多个实例。 2)提供静态全局访问点,供外部调用访问 3)通过锁机制或者static初始化,保证多线程访问单例对象安全。程序如下:
清单1:单例类 config.h
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include <windows.h>
#include <iostream>
using namespace std;
class Config
{
private: //1.构造函数私有
Config()
{
m_path = "config.cfg";
loadGlobalConfig();
}
Config(string path) :m_path(path)
{
loadGlobalConfig();
}
Config(const Config &); //拷贝构造函数不实现,防止拷贝产生多个实例
Config & operator = (const Config &); //复制构造函数不实现,防止赋值产生多个实例
public:
static Config * getInstance() //2.提供全局访问点
{
static Config m_singletonConfig; //3.c++11保证了多线程安全,程序退出时,释放资源
return &m_singletonConfig;
}
void loadGlobalConfig()
{
//std::cout<<"111"<<std::endl;
//Sleep(1000); //休眠1000ms
//std::cout<<"222"<<std::endl;
//加载配置文件......
}
private:
string m_path; //配置文件的路径
};
#endif // _CONFIG_H_
2. static线程安全测试
前面提到,c++11保证了static对象在执行构造函数初始化时的线程安全性。对此c++11中的static变量的该特性,我做了一个实验,验证了static类对象的构造函数线程安全性。撤销清单1中28-30行代码的注释,执行main.cpp。main.cpp代码如下:
清单2 :main.cpp
#include "config.h"
#include <thread>
#define THREAD_NUM 2
void gTestStatic()
{
Config *pConf=Config::getInstance();
}
int main()
{
std::thread threadArray[THREAD_NUM];
for (int i=;i<THREAD_NUM;i++)
{
threadArray[i] = std::thread(&gTestStatic);
}
for (int i = ; i < THREAD_NUM; i++)
{
threadArray[i].join(); //主线程等待所有的线程结束
}
return ;
}
清单3 : 实验结果
output:
从这个实验可以看出,一个线程在执行类的构造函数时休眠1ms,另一个线程在等待,因此static对象的构造函数确实只执行了一次。因此,c++11确实保证了static对象构造函数初始化的多线程安全。
c++:自己动手实现线程安全的c++单例类的更多相关文章
- Java线程和多线程(五)——单例类中的线程安全
单例模式是最广泛使用的创建模式之一.在现实世界之中,诸如Databae的连接或者是企业信息系统(EIS)等,通常其创建都是受到限制的,应该尽量复用已存在对象而不是频繁创建销毁.为了达到这个目的,开发者 ...
- 【线程安全】—— 单例类双重检查加锁(double-checked locking)
1. 三个版本单例类的实现 版本1:经典版 public class Singleton { public static Singleton getInstance() { if (instance ...
- muduo网络库源码学习————线程本地单例类封装
muduo库中线程本地单例类封装代码是ThreadLocalSingleton.h 如下所示: //线程本地单例类封装 // Use of this source code is governed b ...
- MVC 创建线程内的db单例
using System; using System.Collections.Generic; using System.Linq; using System.Web; using LSUnion.S ...
- iOS-主线程刷新UI【+单例】
主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ /// }); 单例 static Tools *_sharedManger; @implem ...
- Spring单例与线程安全小结
一.Spring单例模式与线程安全 Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方. 单例模式的意思就是只有一个实例.单例模式确 ...
- C#单例测试(懒汉式双锁保证线程安全)
单例模式的概念 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 关键点: 这个类只有一个实例,这是最基本的 它必须自行创建 ...
- 【转】Spring Bean单例与线程安全
一.Spring单例模式及线程安全 Spring框架中的Bean,或者说组件,获取实例的时候都是默认单例模式,这是在多线程开发的时候需要尤其注意的地方. 单例模式的意思是只有一个实例,例如在Sprin ...
- java双重检测或枚举类实现线程安全单例(懒汉模式)
双重检测实现 /** * 懒汉模式->双重同步锁单例模式 */ public class SingletonExample5 { private SingletonExample5() { } ...
随机推荐
- Hibernate一对多双向关联映射
建立多对一的单向关联关系 Emp.java private Integer empNo //员工编号 private String empName / ...
- CSS中@import与link的具体区别
我们知道在网页中引用外部CSS有两种方式:@import和link 我们也经常听到有人说要使用link来引入CSS更好,但是你知道为什么吗? 继续往下看 link:link就是把外部CSS与网页连接起 ...
- homebrew常用命令
安装 ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/Go/install)" 搜索 brew sea ...
- Java 注解 入门
这几天在学习Spring3.x,发觉现在许多框架都用上了java注解功能,然后自己就对java注解这方面初步学习了一下. 首先,注解跟注释不是一个意思,也根本不是同一个事物. 注释就是我们平常平常中对 ...
- Springs Element 'beans' cannot have character [children], because the type's content type is element-only
Springs Element 'beans' cannot have character [children], because the type's content type is element ...
- 算法模板——计算几何2(二维凸包——Andrew算法)
实现功能:求出二维平面内一对散点的凸包(详见Codevs 1298) 很神奇的算法——先将各个点按坐标排序,然后像我们所知的那样一路左转,求出半边的凸包,然后反过来求另一半的凸包 我以前正是因为总抱着 ...
- Visual Studio 2017正式版安装
Visual Studio号称宇宙第一IDE, 2017年3月7日强大的微软帝国时隔两年多终于发布新一代IDE Visual Studio 2017.支持的功能简直不能太多,详情移步:https:// ...
- Solr commit 策略测试
已知Solr 的Commit策略: 服务器端: 1)AutoCommit 2)AutoSoftCommit 客户端 Commit 本次我测试了客户端关闭Commit的情况下,服务器端Commit策略的 ...
- Angular企业级开发(9)-前后端分离之后添加验证码
1.背景介绍 团队开发的项目,前端基于Bootstrap+AngularJS,后端Spring MVC以RESTful接口给前端调用.开发和部署都是前后端分离.项目简单部署图如下,因为后台同时采用微服 ...
- 用递归的方式处理数组 && 把递归方法方法定义到数组的原型上 (这是一次脑洞大开的神奇尝试)
在 javascript 里,如果我们想用一个函数处理数组 (Array) 中的每个元素,那我们有很多种选择,最简单的当然就是用自带的 forEach 函数(低版本也可以使用 lodash 中的 fo ...