zoukankan      html  css  js  c++  java
  • 静态构造函数到底执行了多少次?

    我们知道对于class和struct都可以定义构造函数,而构造函数又有实例构造函数和静态构造函数。实例构造函数在每次实例化时,都会执行一次。那静态构造函数是否如此呢?我们先来看一段代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConstructorTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine(CData.Num);///A
                Console.WriteLine(CData.Num);///B           
                Console.ReadLine();
            }
        }
    
        public class CData
        {
            public static int Num = 0;
            static CData()
            {
                Num++;
            }
        }
    }
    
    我们猜测一下执行的结果:

    A行输出的是1.这个比较容易想到,因为Num初始为0,在构造函数中执行了Num++,所以结果为1.

    那B行输出的呢?会不会又执行了一次Num++,导致输出结果为2?我们来看输出的结果,见下图


    我们看到,输出的结果都是1.

    这是为什么?难道说Num++只执行了一次吗?我们设断点来看看。


    从断点的执行顺序上看,每一次调用CData.Num时,进入到了CData的静态构造函数中,使得Num由0变成了1.而第二次调用CData.Num时,不再进入到CData的静态构造函数中,所以Num依然是1。

    所以得出结论:静态构造函数只执行一次。

    那有人会问,如果并发呢?

    并发也依然会执行一次。因为在调用静态构造函数时,会先检测有没有被初始化(即有没有被调用过)。如果有,则直接跳过。如果没有,将进入静态构造函数内部。

    在并发时,当有一个位置A在调用静态构造函数时,会检测该静态构造函数没有被初始化,如果没有被初始化,则进行初始化,并进入同步阻塞状态,其他的位置B虽然在并发调用,但会阻寒在这里。当位置A调用完成后,阻塞状态解除,位置B进入,这时会检测到构造函数已经被初始化了,所以直接跳过。而是否有没有被初始化的标志,是设置在AppDomain(程序域)的层级上的。

    所以静态构造函数非常适合用在单件模式中。我们可以看一段《CLR via C#》一书中的一段说明:


    结论:静态构造函数在程序域的层级确保了只会执行一次,且是线程安全的。所以非常适合于用在单件模式中(或者只需要单一对象的地方)。


    转载请注明出处:http://blog.csdn.net/xxdddail/article/details/38058121


  • 相关阅读:
    你不知道的多重循环的事情
    【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 & 纹理混合
    ssh 远程登陆指定port
    GMT和CST的转换
    Swift新手教程系列5-函数+selector在swift中的使用方法
    Mac OS X 10.10, Eclipse+ADT真机调试代码时,Device Chooser中不显示真机的解决方式
    android studio 0.8.1使用和遇到问题解决
    C语言之函数调用17—递归法之中的一个般函数的调用(2)
    C语言之基本算法25—牛顿迭代法求方程近似根
    FineUI之使用SQL脚本从数据库表中生成对应的输入控件
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604991.html
Copyright © 2011-2022 走看看