.Net Static 与单例
Static 关键字作为修饰符可以用于类、方法和成员变量上。其含义是对于整个应用程序生命周期内,访问该修饰符修饰的对象/方法/变量都引用到同一实例(内存地址)。但正因如此在多线程下会出现线程安全问题:计数器字段count是静态的,在多线程下循环调用1000次Increase方法,得到的结果未必是1000
internal class Counter
{
public static int count = ; public static void Increase()
{
Thread.Sleep();
Counter.count++;
}
}
要解决这个问题,首先要了解Static的特性:
1.若修饰一个变量,即使是个值类型,如Int变量,该变量无论在何处使用都是同一个实例(内存地址)。此时它表现出了引用类型的特性,在方法中调用该静态变量,不是将该值类型放入栈中,而是指向该变量的指针。
2.静态类、变量、方法的内存分配是在应用程序编译时就已确定的,在应用程序初始化时就已分配好的,当应用程序生命周期结束时才被销毁。且他们既不存储在栈上也不在堆上,而是静态数据区中。正因如此才能被整个应用程序全局的访问到同一实例。 这里有一篇文章描述了静态存储区的详细:http://www.educity.cn/zk/bianyi/201307031614161496.htm
3.静态类不能继承或实例化,不能有普通构造函数,但可以有静态构造,用来初始化其中的静态成员。静态类只能有静态成员或方法。
4.静态构造函数既可以用在静态类中又可以用在普通类中。其作用就是为了提供合适的时机初始化静态成员。对于一个普通类里的静态成员,在应用程序启 动时即被初始化,此时连main函数都未开始执行,普通构造函数更是无法被调用。而拥有静态构造方法的类,其静态成员初始化将被延后到一旦类内任何静态成 员或静态方法被实际调用时,才会触发默认的初始化,然后是触发静态构造方法。静态构造只能被调用一次,只能初始化静态成员。若直接初始化该类,则静态构造先触发,再触发普通构造函数。
由此可见,最根本的原因是在同一时刻有两个线程同时访问静态资源,资源的状态同时修改而导致的。因此需要对共享资源局部串行化,也即线程安全的单例。
internal class LockCounter
{
public static int count = ; public static void Increase()
{
Thread.Sleep();
lock (typeof(LockCounter))
{ LockCounter.count++;
}
}
}
更进一步的,可以不适用Lock而是使用InterLocked进行原子操作
internal class InterLockCounter
{
public static int count = ; public static void Increase()
{
Thread.Sleep();
Interlocked.Increment(ref InterLockCounter.count);
}
}
而如果我们利用静态构造的该特性,我们可以将它用在实现简洁无锁的单例模式,而且是线程安全的,因为任何试图访问实例的线程都会触发静态构造初始化该对象实例之后才能访问,且静态构造只能被调用一次,不会出现多线程问题。
.Net Static 与单例的更多相关文章
- static实现单例的隐患
1. 前言 Java的单例有多种实现方式:单线程下的简单版本.无法在指令重排序下正常工作的Double-Check.static.内部类+static.枚举--.这篇文章要讨论的,是在使用static ...
- 有关线程安全的探讨--final、static、单例、线程安全
我的代码中已经多次使用了线程,然后还非常喜欢使用据说是线程不安全的静态方法,然后又看到很多地方最容易提的问题就是这个东西线程不安全 于是我不免产生了以下几个亟待解决的问题: 什么样的代码是天生线程 ...
- C++中模板单例的跨SO(DLL)问题:RTTI,typeid,static,单例
(转载请注明原创于潘多拉盒子) C++的模板可以帮助我们编写适合不同类型的模板类,给代码的复用性提供了极大的方便.近来写了一个涉及单例的C++模板类,简化下来可以归结为以下的代码: template ...
- iOS - Swift SingleClass 单例类
前言 单例对象能够被整个程序所操作.对于一个单例类,无论初始化单例对象多少次,也只能有一个单例对象存在,并且该对象是全局的,能够被整个系统访问到. 单例类的创建 1.1 单例类的创建 1 单例类的创建 ...
- 多个so中模板单例的多次实例化
在Android打包项目时,发现登录功能不能使用了,logcat中也没发现什么问题,最后一行一行log定位到了问题.原来是一个so文件中的构造函数被初始化二次! 这个单例是通过继承模板来实现的(暂 ...
- koa 基础(十九)es6中的单例
1.app.js /** * es6中的单例 * 实例化的时候,无论实例多少次,构造函数只执行一次,有利于提高性能 */ class Db { static getInstance() { /*单例* ...
- 算法、数据结构、与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design)
算法.数据结构.与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design) 作者: Compasslg 李涵威 1. 什么是单例设计(Singleton Design) 在学 ...
- 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类
static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ...
- 单例 与 static
单例的构造器是private的,不能直接用new 创建对象.static虽然可以随时使用,但是还是有被重新创建的可能. 举个例子,你希望任何时候有一个class A的实例就可以了class B { ...
随机推荐
- C#中位、字节等知识
本文介绍C#中位.字节等知识. 1. 位(bit) 位(bit)有叫做比特,指二进制中的一位,是二进制的最小信息单位. bit也被称作小b,用b表示. 2. 字节(bytes) 8位表示一个字节. 由 ...
- iis 支持html执行php输出
iis 支持html执行php输出 2012-07-25 10:50:23| 分类: PHP|举报|字号 订阅 在HTML中有个简单的的PHP随机数需要输出,例如: <td backg ...
- win7 文件共享 xp
前几天因为需要将win7内一文件夹共享给XP使用,因为NT5跟NT6安全机制的问题,共享的实现没有XP共享的方便,很多人是牺牲(关闭)了win7的系统防火墙才达到共享给XP的目的,但是关闭防火墙势必会 ...
- oracle数据库连接字符串
不在项目加入tsname.ora的托管写法: <add name="CONN" connectionString="data source=127.0.0.1:15 ...
- [网络]远程访问局域网svn服务器[转]
转至:http://8474832.blog.51cto.com/8464832/1555449 打开路由器访问界面 选择转发规则->端口映射-新建 在弹出的界面中填写相应的端口号了内网ip 填 ...
- yii缓存设置使用
'filecache'=>array( 'class'=>'system.caching.CFileCache', 'directoryLevel'=>'3',), //在main. ...
- iOS开发-用预处理指令代替注释
有时候我们在调试程序的时候,想不执行某一段代码或者某些方法,我们会用注释,但是这样看上去就会让你的代码显示“很绿”,此时我们可以用一下代码 #if 0 // 你不想执行的代码 #endif 这样就可以 ...
- MFC中修改静态文本框中文字的字体、颜色
假设有一个静态文本框控件,其ID为:IDC_STATIC_XSDJ,且关联一个control类的CStatic类型的变量m_static_xsdj. 设置字体时自然要用到CFont类,下面介绍两种方法 ...
- T4模板语法
T4,即4个T开头的英文字母组合:Text Template Transformation Toolkit. T4文本模板,即一种自定义规则的代码生成器.根据业务模型可生成任何形式的文本文件或供程序调 ...
- ghostDoct 使用 (转 http://www.cnblogs.com/RockyMyx/archive/2010/04/20/Project-Route-Using-GhostDoc.html)
一.简介 GhostDoc是Visual Studio的一个免费插件,可以为开发人员自动生成XML格式的注释文档. 二.下载 需要的朋友可以去这里下载,填个Email地址就可以下了:GhostDoc下 ...