asp.net中C++单例实现问题分析_.Net教程
推荐:简单理解Web Service三种实现方式Web Service概念: 根据W3C的定义,Web服务(Web service)应当是一个软件系统,用以支持网络间不同机器的互动操作。网络服务通常是许多应用程序接口(API)所组成的,它们通过网络的远程服务器端,执行客户所提交服务的请求。简单的来说就是服务器端向客户端提供服务。 We
方案一
这是最简单的版本,在单线程下(或者是C++0X下)是没任何问题的,但在多线程下就不行了,因为static QMManager instance_;这句话不是线程安全的。
在局部作用域下的静态变量在编译时,编译器会创建一个附加变量标识静态变量是否被初始化,会被编译器变成像下面这样(伪代码):
这里有竞争条件,两个线程同时调用instance()时,一个线程运行到if语句进入后还没设constructed值,此时切换到另一线程,constructed值还是false,同样进入到if语句里初始化变量,两个线程都执行了这个单例类的初始化,就不再是单例了。
方案二
一个解决方法是加锁:
但这样每次调用instance()都要加锁解锁,代价略大。
方案三
那再改变一下,把内部静态实例变成类的静态成员,在外部初始化,也就是在include了文件,main函数执行前就初始化这个实例,就不会有线程重入问题了:
这被称为饿汉模式,程序一加载就初始化,不管有没有调用到。
看似没问题,但还是有坑,在一个2B情况下会有问题:在这个单例类的构造函数里调用另一个单例类的方法可能会有问题。
看例子:
这里QMManager的构造函数调用了QMSqlite的instance函数,但此时QMSqlite::instance_可能还没有初始化。
这里的执行流程:程序开始后,在执行main前,执行到QMManager QMManager::instance_;这句代码,初始化QMManager里的instance_静态变量,调用到QMManager的构造函数,在构造函数里调用QMSqlite::instance(),取QMSqlite里的instance_静态变量,但此时QMSqlite::instance_还没初始化,问题就出现了。
那这里会crash吗,测试结果是不会,这应该跟编译器有关,静态数据区空间应该是先被分配了,在调用QMManager构造函数前,QMSqlite成员函数在内存里已经存在了,只是还未调到它的构造函数,所以输出是这样:
QMManager constructor
QMSqlite do_something
QMSqlite constructor
方案四
那这个问题怎么解决呢,单例对象作为静态局部变量有线程安全问题,作为类静态全局变量在一开始初始化,有以上2B问题,那结合下上述两种方式,可以解决这两个问题。boost的实现方式是:单例对象作为静态局部变量,但增加一个辅助类让单例对象可以在一开始就初始化。如下:
结合方案3的.cpp,这下可以看到正确的输出和调用了:
QMManager constructor
QMSqlite constructor
QMSqlite do_something
来看看这里的执行流程:
初始化QMManager类全局静态变量create_object_
->调用object_creator的构造函数
->调用QMManager::instance()方法初始化单例
->执行QMManager的构造函数
->调用QMSqlite::instance()
->初始化局部静态变量QMSqlite instance
->执行QMSqlite的构造函数,然后返回这个单例。
跟方案三的区别在于QMManager调用QMSqlite单例时,方案3是取到全局静态变量,此时这个变量未初始化,而方案四的单例是静态局部变量,此时调用会初始化。
跟最初方案一的区别是在main函数前就初始化了单例,不会有线程安全问题。
最终boost
上面为了说明清楚点去除了模版,实际使用是用模版,不用写那么多重复代码,这是boost库的模板实现:
其实Boost库这样的实现像打了几个补丁,用了一些奇技淫巧,虽然确实绕过了坑实现了需求,但感觉挺不好的。
分享:Asp.net中Ajax与JQuery的ready函数冲突怎么办Asp.net Ajax和Asp.net结合得很完美,发现不够用的时候,难免想到了Jquery。一般Jquery和Asp.net Ajax这两样东西结合使用也常见,如果处理好的话,并不会冲突。但最近发现Jquery的ready()函数在PostBack回来的时候,ready里执行的动作竟然无效了,第一印象:会不会Asp.
- 简单理解Web Service三种实现方式
- Asp.net中Ajax与JQuery的ready函数冲突怎么办
- asp.net中Repeater控件用法笔记
- asp.net中导出excel数据的方法汇总
- Asp.Net 上传图片并生成高清晰缩略图
- 服务器安全狗导致ASP.NET网站运行出错的一个案例
- Asp.Net其他页面如何调用Web用户控件写的分页
- ASP.NET中上传并读取Excel文件数据示例
- asp.net SqlParameter如何根据条件有选择的添加参数
- asp.net Xml绑定到数据控件的具体实现
- asp.net显示自己的网页图标的几种方式
- ASP.NET连SQL7接口源代码
- 相关链接:
- 教程说明:
.Net教程-asp.net中C++单例实现问题分析。