C++多线程下的单例模式
1 教科书里的单例模式
我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例。
上代码:
class singleton
{
protected:
singleton(){}
private:
static singleton* p;
public:
static singleton* instance();
};
singleton* singleton::p = NULL;
singleton* singleton::instance()
{
if (p == NULL)
p = new singleton();
return p;
}
这是一个很棒的实现,简单易懂。但这是一个完美的实现吗?不!该方法是线程不安全的,考虑两个线程同时首次调用instance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误!同时,这也不是单例的唯一实现!
一、懒汉模式:即第一次调用该类实例的时候才产生一个新的该类实例,并在以后仅返回此实例。
需要用锁,来保证其线程安全性:原因:多个线程可能进入判断是否已经存在实例的if语句,从而non thread safety.
使用double-check来保证thread safety.但是如果处理大量数据时,该锁才成为严重的性能瓶颈。
1、静态成员实例的懒汉模式:
class Singleton
{
private:
static Singleton* m_instance;
Singleton(){}
public:
static Singleton* getInstance();
}; Singleton* Singleton::getInstance()
{
if(NULL == m_instance)
{
Lock();//借用其它类来实现,如boost
if(NULL == m_instance)
{
m_instance = new Singleton;
}
UnLock();
}
return m_instance;
}
2、内部静态实例的懒汉模式
这里需要注意的是,C++0X以后,要求编译器保证内部静态变量的线程安全性,可以不加锁。但C++ 0X以前,仍需要加锁。
class SingletonInside
{
private:
SingletonInside(){}
public:
static SingletonInside* getInstance()
{
Lock(); // not needed after C++0x
static SingletonInside instance;
UnLock(); // not needed after C++0x
return &instance;
}
};
使用实例:
#include<iostream>
using namespace std;
class CSingleton
{
private:
CSingleton() {
}
~CSingleton() {
if (m_pInstance == NULL) {
return;
}
delete m_pInstance;
m_pInstance = NULL;
}
static CSingleton *m_pInstance;
public:
static CSingleton * GetInstance() {
if(m_pInstance == NULL)
m_pInstance = new CSingleton();
return m_pInstance;
}
};
CSingleton* CSingleton::m_pInstance = NULL;//类的静态成员变量需要在类外边初始化 class SingletonInside
{
private:
SingletonInside(){}
public:
static SingletonInside* getInstance()
{
static SingletonInside instance;
return &instance;
}
void init(){
m_data = ;
}
void set(){
++m_data;
}
int m_data;
}; int main() { SingletonInside* single1 = SingletonInside::getInstance();
SingletonInside* single2 = SingletonInside::getInstance(); single1->set();
if (single1 == single2) {
cout<<"Same"<<endl;
single1->init();
single1->set();
cout<<single2->m_data <<endl;
}else{
cout<<"not =="<<endl;
}
return ;
}
output:
Same
11
二、饿汉模式:即无论是否调用该类的实例,在程序开始时就会产生一个该类的实例,并在以后仅返回此实例。
由静态初始化实例保证其线程安全性,WHY?因为静态实例初始化在程序开始时进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题。
故在性能需求较高时,应使用这种模式,避免频繁的锁争夺。
class SingletonStatic
{
private:
static const SingletonStatic* m_instance;
SingletonStatic(){}
public:
static const SingletonStatic* getInstance()
{
return m_instance;
}
}; //外部初始化 before invoke main
const SingletonStatic* SingletonStatic::m_instance = new SingletonStatic;
特点与选择:
由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
在访问量较小时,采用懒汉实现。这是以时间换空间。
C++多线程下的单例模式的更多相关文章
- java集群优化——多线程下的单例模式
在最初学习设计模式时,我为绝佳的设计思想激动不已,在以后的project中.多次融合设计模式,而在当下的设计中.我们已经觉察出了当初设计模式的高瞻远瞩.可是也有一些不足,须要我们去改进.有人说过.世界 ...
- Java 多线程下的单例模式
单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.正是由于这个特 点,单例对象通常作为程序中的存放配置信息的载体,因为它能保证 ...
- C++模式设计-多线程下的单例模式
1 教科书里的单例模式 我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实 ...
- ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开
ASP.NET MVC Filters 4种默认过滤器的使用[附示例] 过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响 ...
- 关于Spring在多线程下的个人疑问
在Web开发中,不可避免的是需要遇到并发操作的,并发操作就有可能会引发我们的多线程安全问题.比如说,我们多线程下访问同一个变量并且有一个线程做出修改那么就会使得我们另外的线程在不知情的情况下被修改自己 ...
- 对于多线程下Servlet以及Session的一些理解
今天,小伙伴突然问到了Servlet是不是线程安全的问题.脑子当时一卡壳,只想到了单实例多线程.这里做一些总结. Servlet体系是建立在Java多线程的基础之上的,它的生命周期是由Tomcat来维 ...
- java 单例的实现及多线程下的安全
package com.demo01; public class Single { /** * 设计模式:单例设计模式 * 解决一个类中只允许存在一个对象这种情况: * 不允许通过类,无限制的创建该类 ...
- Java进阶专题(十五) 从电商系统角度研究多线程(下)
前言 本章节继上章节继续梳理:线程相关的基础理论和工具.多线程程序下的性能调优和电商场景下多线程的使用. 多线程J·U·C ThreadLocal 概念 ThreadLocal类并不是用来解决 ...
- 多线程下NSOperation、NSBlockOperation、NSInvocationOperation、NSOperationQueue的使用
本篇文章主要介绍下多线程下NSOperation.NSBlockOperation.NSInvocationOperation.NSOperationQueue的使用,列举几个简单的例子. 默认情况下 ...
随机推荐
- iOS应用支持IPV6
一.IPV6-Only支持是啥? 首先IPV6,是对IPV4地址空间的扩充.目前当我们用iOS设备连接上Wifi.4G.3G等网络时,设备被分配的地址均是IPV4地址,但是随着运营商和企业逐渐部署IP ...
- Sencha Touch 2.2.1 Custom Icon 自定义图标
ST2.2版本竟然又改变了sass中自定义图标的添加方式,在2.2以前采用的是这种base64的方式,详见:http://www.cnblogs.com/qidian10/archive/2012/1 ...
- 如何使用网盘托管git项目
话说近年来git已经成为项目源代码管理的标准工具,有不少免费托管网站可供使用,详情参考这篇文章: http://www.cnblogs.com/zdz8207/archive/2012/05/20/2 ...
- http://crunchify.com/simplest-spring-mvc-hello-world-example-tutorial-spring-model-view-controller-tips/ 非常棒的spring入门,maven,以及eclipse
http://crunchify.com/simplest-spring-mvc-hello-world-example-tutorial-spring-model-view-controller-t ...
- pthread clean up
https://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part4/ http://www.cnblogs.com/xfi ...
- 32和64位的CentOS 6.0下 安装 Mono 2.10.8 和Jexus 5.0
http://www.cnblogs.com/shanyou/archive/2012/01/07/2315982.html shanyou 博客
- 关于FlexPaper 2.1.2版本 二次开发 Logo 、打印、搜索、缩略图、添加按钮、js交互、右键菜单、书签等相关问题
2015-03-02 更新文章,由于需求修改,更改了flexpaper插件,故增加第9.10.11小节,下载代码时请注意. 先废话几句.最近用到文档在线浏览功能,之前用的是print2flash(一个 ...
- HDOJ 1536 S-Nim
S-Nim Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- PHP访问数据,增删改
主页面 <h1>主页面</h1> <table width="100%" border="1" cellpadding=" ...
- zhx's contest (矩阵快速幂 + 数学推论)
zhx's contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) To ...