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 与单例的更多相关文章

  1. static实现单例的隐患

    1. 前言 Java的单例有多种实现方式:单线程下的简单版本.无法在指令重排序下正常工作的Double-Check.static.内部类+static.枚举--.这篇文章要讨论的,是在使用static ...

  2. 有关线程安全的探讨--final、static、单例、线程安全

    我的代码中已经多次使用了线程,然后还非常喜欢使用据说是线程不安全的静态方法,然后又看到很多地方最容易提的问题就是这个东西线程不安全   于是我不免产生了以下几个亟待解决的问题: 什么样的代码是天生线程 ...

  3. C++中模板单例的跨SO(DLL)问题:RTTI,typeid,static,单例

    (转载请注明原创于潘多拉盒子) C++的模板可以帮助我们编写适合不同类型的模板类,给代码的复用性提供了极大的方便.近来写了一个涉及单例的C++模板类,简化下来可以归结为以下的代码: template ...

  4. iOS - Swift SingleClass 单例类

    前言 单例对象能够被整个程序所操作.对于一个单例类,无论初始化单例对象多少次,也只能有一个单例对象存在,并且该对象是全局的,能够被整个系统访问到. 单例类的创建 1.1 单例类的创建 1 单例类的创建 ...

  5. 多个so中模板单例的多次实例化

    在Android打包项目时,发现登录功能不能使用了,logcat中也没发现什么问题,最后一行一行log定位到了问题.原来是一个so文件中的构造函数被初始化二次!   这个单例是通过继承模板来实现的(暂 ...

  6. koa 基础(十九)es6中的单例

    1.app.js /** * es6中的单例 * 实例化的时候,无论实例多少次,构造函数只执行一次,有利于提高性能 */ class Db { static getInstance() { /*单例* ...

  7. 算法、数据结构、与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design)

    算法.数据结构.与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design) 作者: Compasslg 李涵威 1. 什么是单例设计(Singleton Design) 在学 ...

  8. 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类

    static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ...

  9. 单例 与 static

    单例的构造器是private的,不能直接用new 创建对象.static虽然可以随时使用,但是还是有被重新创建的可能. 举个例子,你希望任何时候有一个class A的实例就可以了class B {  ...

随机推荐

  1. c++builder Color

    procedure ExtractRGB(const Color: Graphics.TColor; out Red, Green, Blue: Byte); var RGB: Windows.TCo ...

  2. centos安装postfixadmin

    postfixadmin的安装,跟普通网站安装没什么区别 配置好虚拟目录,然后在数据库中创建数据库postfix 修改config.inc.php文件,详细搜索谷歌 访问http://www.你的域名 ...

  3. datagridview自动填充列头

    //填充datagridview dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

  4. 编译安装-Apache

    一.配置选项说明 二.安装apache 1.环境准备 2.安装apr 3.安装apr-util 4.安装pcre 5.安装httpd 6.修改配置文件 7.开机自启动 8.注册为服务 9.测试 一.配 ...

  5. JAVA 开发实例 一 移动的小球

    package com.java.move; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; i ...

  6. IE下判断IE版本的语句...[if lte IE 6]……[endif]

    <!--[if lte IE 6]> <![endif]--> IE6及其以下版本可见 <!--[if lte IE 7]> <![endif]--> ...

  7. C:内存分配、内存中五大区

     1.内存的划分  (从高到低依次是: 栈区 . 堆区 .全局静态区 . 常量区 . 代码区 )栈区是系统自动回收,堆区是我们手动回收  2. 栈区   在函数内部定义的局部变量和数组.都存放在栈区, ...

  8. CloudStack4.2 更新全局参数API

    测试更新全局参数API http://192.168.153.34:8080/client/api?command=updateConfiguration&response=json& ...

  9. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据(转载)

    本文转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Had ...

  10. VPW Communication Protocol

    http://www.fastfieros.com/tech/vpw_communication_protocol.htm Breakdown of the j1850 3 byte Header f ...