.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 { ...
随机推荐
- ArcGIS Desktop打开慢的解决办法
问题:ArcGIS Desktop打开巨慢,不管是ArcMap还是CataLog都是一样的,打开一次有时候需要10多分钟. 解决方法:C:\Users\[用户名]\AppData\Roaming\ES ...
- Tagged Pointers
[Tagged Pointers] 1.what is tagged pointer? 2.原理剖析
- HDU 1787 GCD Again(欧拉函数,水题)
GCD Again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- UVa 10316 - Airline Hub
题目:给出地球上的n个机场的经度和纬度,想在这里面确定一个HUB使得他到其他机场的最大距离最小. 分析:计算几何.大地坐标系.因为数据不大直接枚举即可,比较时利用圆心角可以提高计算效率,并控制精度. ...
- 无责任Windows Azure SDK .NET开发入门篇三[使用Azure AD 管理用户信息--3.3 Details用户详细信息]
3.3 Details用户详细信息 用户详细信息是通过objectId获取.代码如下 public async Task<ActionResult> Details(string obje ...
- ?this&函数自身的引用
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Gson 和 Fastjson 你不知道的事
背景 目前在公司负责的业务, 主要是跟JSON数据打交道, fastjson .gson都用, 他们适用于不同场景.fastjson号称是业界处理json效率最高的框架, 没有之一.但在某些场景下, ...
- Flex Builder 开发语言切换问题
1.Flex Builder 4.6切换语言 打开\Adobe\Adobe Flash Builder 4.6\FlashBuilder.ini -nlzh_CN-startupeclipse/plu ...
- 使用jquery获取父元素或父节点的方法
今天面试题问到了,没答上,jq要继续学习啊 jquery获取父元素方法比较多,比如parent(),parents(),closest()这些都能帮你实现查找父元素或节点,下面我们来一一讲解: 先举个 ...
- 关于Collection'
---恢复内容开始--- 众所周知在我们使用Java中的类的存储的时候经常会使用一些容器,链表的概念,本文将彻底帮您弄清链表的各种概念和模型!!!!注 意理解哦~~~ 大致框架如下: ----> ...