在c#中调用静态方法时会发生什么
本文关键字:什么 静态方法 调用 | 更新日期: 2023-09-27 18:18:41
当您创建一个类的实例时,该实例中的所有变量都是特定于该实例的,并且在实例超出作用域时被杀死。但是它是如何在静态方法中工作的呢?假设两个人同时调用System.Math.Abs()。运行时如何区分这两个调用者?这就是线程的由来吗?是否为每个调用者自动创建单独的线程?
当你创建一个类的实例时,当实例超出作用域时,所有特定于该实例的变量都将被终止。
变量——通常称为"字段"——在实例的生存期之后被释放。作用域是程序文本的一个区域,在这个区域中,编译器通过名字来识别某些东西;liftime是存储位置在中有效的部分。作用域和生命周期经常混淆。
但是它是如何在静态方法中工作的呢?
静态域具有无限的生存期;存储位置是在该字段被访问之前的某个时间创建的,直到appdomain被拆除才会被销毁。
假设两个人同时调用System.Math.Abs()。
OK。你认为这是怎么发生的?
运行时如何区分两个调用者?这就是线程的由来吗?
静态方法被转换成一堆机器指令,这些指令是内存中的数字。每个执行线程都有一个与之相关联的数字,称为指令指针,它定位当前指令。两个不同的线程可以同时拥有同一个静态方法内部的指令指针。
是否为每个调用者自动创建单独的线程?
这个问题没有意义。如果两个调用者不在单独的线程上,如何同时获得 ?
就方法变量生命周期而言,静态方法和非静态方法之间没有真正的区别。在这两种情况下,作为实现细节,局部变量通常(并非总是如此:有例外)在堆栈上分配。堆栈是每个线程的,所以本地方法变量不会在线程之间交叉。
实例方法和静态方法的唯一区别是实例方法有一个隐式的第零参数,即"this",它是由调用者推送的(加上一些虚拟调度和null检查)。
为简单起见,我省略了迭代器块、捕获的变量等
即使不存在类的实例,也存在类的所有静态成员。它们在第一次使用之前被初始化,并在程序完成时被清理。
如果有两个对静态方法的同时调用,它们将使用类的任何静态成员的相同副本(如果它们使用它们)。因此,如果静态方法对静态成员(或参数)进行操作,它应该以线程安全的方式进行操作。如果静态方法只对局部对象操作,那么该方法本身通常是线程安全的。
至于运行时如何区分两个调用者,这是线程的本质。每个线程都有自己的调用堆栈,其中包含任何本地变量、参数、返回地址等的副本。因此,两个调用不会混淆,并且每个调用都正确地返回给调用者。唯一需要注意的是,如果静态方法操作的静态成员不是线程安全的(或者参数不是线程安全的)。