Singleton、MultiThread、Lib——实现单实例无锁多线程安全API
一、singleton double check
SingleInstance* volatile g_instance = NULL;
cswuyg::MyCritical g_cs;
SingleInstance* GetInstance()
{
if (g_instance == NULL)
{
cswuyg::Lock<> lock(g_cs);
if (g_instance == NULL)
{
g_instance = new SingleInstance;
}
}
return g_instance;
}
MemoryBarrier宏
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686355(v=vs.85).aspx
这篇文章表示,vs2005以后的volatile已经包含了memory barrier的功能,并介绍了有几类函数是不会被调换执行顺序的。
http://stackoverflow.com/questions/19652824/why-can-memorybarrier-be-implemented-as-a-call-to-xchg/19652910#19652910
它介绍了为什么x86机器上的xchg可以消灭掉CPU的reorder。
二、导出Lib中慎用全局对象 & 原子操作代替锁


SingleInstance* volatile g_instance;
LONG volatile g_for_lock; SingleInstance* GetInstance()
{
if (g_instance == NULL)
{
LONG pre_value = ::InterlockedExchange(&g_for_lock, );
if (pre_value != )
{
while(g_instance == NULL)
{
::Sleep();
}
}
if (g_instance == NULL)
{
g_instance = new SingleInstance;
}
}
return g_instance;
}
全局的g_for_lock在PE文件装入内存时就初始化为0,所以不存在初始化问题;InterlockedExchange 适用于xp、win7、win8,不存在系统限制;多个线程同时调用InterlockedExchange,只能有一个线程得到0,保证只初始化一次,其余线程进入while循环等待,直到g_point非空。问题不逼你,你就不会想到还有这么好的实现思路 :)
使用原子操作还可以很容易的实现临界区锁的功能,这里就不说了。
三、PE文件中的Lib库全局变量
Double Check 相关资料(主要是说执行指令调整导致在多核机器上某个线程会返回半成品对象,导致DoubleCheck思路失效):
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
http://zh.wikipedia.org/wiki/%E5%8F%8C%E9%87%8D%E6%A3%80%E6%9F%A5%E9%94%81%E5%AE%9A%E6%A8%A1%E5%BC%8F
2014.3.8补充:
抛出异常问题:对于导出API还需要注意不能影响到使用者进程的运行,所以不能抛出exception,需要这么做:1、在API实现处,使用__try...__except把所有逻辑封起来;2、在API的入口处设置非法参数、纯虚函数调用错误处理(_invalid_parameter_handler、_set_purecall_handler),并在出口处还原以便不修改外界设置,这里要解决的是CRT抛出的错误,它跟SEH没关系,所以使用__try...__except无法catch住,这两函数的相关知识参考:《windows下的dump捕获》http://www.cnblogs.com/cswuyg/p/3207576.html。
2014.3.13补充:
编译依赖问题:EXE C依赖Lib B,Lib B依赖Lib A,如果Lib A使用了预编译,那么会出现这种链接错误:error LNK2011: precompiled object not linked in; image may not run,有两种解决方案:1、让EXE C能接触到Lib A工程,保证EXE C在链接的时候能找到Lib A所有相关的中间产物,这个方案我不能采用,因为对外提供的只是Lib B SDK,不是源码;2、Lib A不使用预编译,这个方案比较方便,不过不使用预编译后会增加编译时间,由于Lib A工程比较小,可以接受。 另外,Lib B如何包含Lib A的问题可以参考:http://www.cnblogs.com/cswuyg/archive/2012/02/03/2336424.html
Singleton、MultiThread、Lib——实现单实例无锁多线程安全API的更多相关文章
- 深入浅出单实例Singleton设计模式
深入浅出单实例Singleton设计模式 陈皓 单实例Singleton设计模式可能是被讨论和使用的最广泛的一个设计模式了,这可能也是面试中问得最多的一个设计模式了.这个设计模式主要目的是想在整个系统 ...
- 实现单实例多线程安全API问题
前阵子写静态lib导出单实例多线程安全API时,出现了CRITICAL_SECTION初始化太晚的问题,之后查看了错误的资料,引导向了错误的理解,以至于今天凌晨看到另一份代码,也不多想的以为singl ...
- 无锁,线程安全,延迟加载的单例实现(C#)
单例(singleton)是非常常见,也非常有用的设计模式,当然了, 面试中也是经常会被问到的:)在几乎所有的项目中都能看到它的身影.简而言之,单例保证了一个自定义类型在整个程序的生命周期只被创建一次 ...
- 8.2 GOF设计模式一: 单实例模式 SingleTon
GOF设计模式一: 单实例模式 SingleTon 整个美国,只有一个“现任美国总统” 比如,在学校,“老师”,有数百个:“校长”,只有一个 系统运行时,如何保证某个类只允许实例化一个对象 ...
- 单实例Singleton
单实例Singleton设计模式可能是被讨论和使用的最广泛的一个设计模式了,这可能也是面试中问得最多的一个设计模式了.这个设计模式主要目的是想在 整个系统中只能出现一个类的实例.这样做当然是有必然的, ...
- 设计模式之单实例模式(Singleton)
原理:将类的构造函数由pubic变为private或者protect,添加获取对象的public 成员函数,返回指向对象的静态指针. 首先来一段简单的代码实现 代码一 class Singleton ...
- 单实例redis分布式锁的简单实现
redis分布式锁的基本功能包括, 同一刻只能有一个人占有锁, 当锁被其他人占用时, 获取者可以等待他人释放锁, 此外锁本身必须能超时自动释放. 直接上java代码, 如下: package com. ...
- 无锁编程 - Double-checked Locking
Double-checked Locking,严格意义上来讲不属于无锁范畴,无论什么时候当临界区中的代码仅仅需要加锁一次,同时当其获取锁的时候必须是线程安全的,此时就可以利用 Double-check ...
- 【DPDK】【ring】从DPDK的ring来看无锁队列的实现
[前言] 队列是众多数据结构中最常见的一种之一.曾经有人和我说过这么一句话,叫做“程序等于数据结构+算法”.因此在设计模块.写代码时,队列常常作为一个很常见的结构出现在模块设计中.DPDK不仅是一个加 ...
随机推荐
- XAF应用开发教程(六)控制器
是的,XAF也是MVC结构的,但不仅限于MVC,ViewModel也存在,它是一项复合技术,AOP,ORM,MVC都有. 真实运行的系统中,仅有增删改查功能肯定是远远不够的,ERP.CRM等系统的开发 ...
- 从输入 URL 到页面加载完的过程中都发生了什么事情?
1) 把URL分割成几个部分:协议.网络地址.资源路径.其中网络地址指示该连接网络上哪一台计算机,可以是域名或者IP地址,可以包括端口号:协议是从该计 算机获取资源的方式,常见的是HTTP.FTP,不 ...
- Android Studio常见问题 -- AndroidManifest.xml 覆盖问题
问题如下 D:\source-code\AndroidStudio\MyApplication\app\src\main\AndroidManifest.xmlError:(14, 9) Attrib ...
- JZs3c2440学习笔记一
1.连线 串口线usb-com,USB下载线 2.驱动安装 USB-serial, dnw的sec s3c2410x test驱动安装(win7下安装方法搜索:百问网WIN7,64,dnw) 3.烧 ...
- PHP基础知识之————PDO预处理语句
转载处:http://www.cnblogs.com/xiaohuochai/p/6133353.html 定义 在生成网页时,许多PHP脚本通常都会执行除参数之外,其他部分完全相同的查询语句,针对这 ...
- nodejs学习笔记<五>npm使用
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题. 以下是几种常见使用场景: 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从NPM服务器下载并 ...
- phpmailer发送邮件 SMTP Error: Could not authenticate 错误
这个错误说明虚拟主机不支持PHPMailer默认调用的fsockopen函数,找到class.smtp.php文件,搜索fsockopen,就找到了这样一段代码: $this->smtp_con ...
- Asp.Net_Web身份验证
百度一下”asp.net身份认证“,你会得到很多相关的资料,这些资料通常上来就会介绍诸如”Form认证“”Windows认证“等内容,而没有给出一个完整的流程.初学者对此往往一头雾水,我也曾经被坑过很 ...
- php防止sql注入
[一.在服务器端配置] 安全,PHP代码编写是一方面,PHP的配置更是非常关键. 我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最 ...
- STM8s窗口看门狗
看看窗口看门狗的框图 从图里看出产生复位信号有2个方式: 1 WDGCR寄存器的T6 由1变0,也就是从此寄存器的值从0x40变成0x3F会产生复位信号: 2 当寄存器WDGCR的值大于WDGWR的时 ...