当您创建类的实例时,该实例中的所有变量都特定于该实例,并在实例超出范围时被杀死。但它如何在静态方法中工作?假设有两个人在同一时间调用System.Math.Abs()。运行时如何区分两个调用者?这是线程进来的地方吗?是否为每个调用者自动创建了单独的线程?
答案 0 :(得分:12)
当您创建类的实例时,当实例超出范围时,将杀死特定于该实例的所有变量。
在实例的生命周期之后,通常称为“字段”的变量将被解除分配。 范围是程序文本的区域,编译器通过其名称识别某些内容; liftime 是部分时间,在此期间存储位置有效。范围和寿命经常混淆。
但它如何在静态方法中起作用?
静态场具有无限的生命周期;存储位置是在访问字段之前的某个时间创建的,并且在应用程序域被拆除之前不会被销毁。
假设有两个人在同一时间调用System.Math.Abs()。
行。您如何提出这种情况?
运行时如何区分两个呼叫者?这是线程进入的地方吗?
静态方法被嵌入到一堆机器指令中,这些指令是内存中的数字。每个执行线程都有一个与之关联的数字,称为指令指针,用于定位当前指令。两个不同的线程都可以同时具有同一静态方法内的指令指针。
是否为每个来电者自动创建了单独的线程?
这个问题没有任何意义。如果他们不是已经在不同的线程上,你是如何同时获得两个的?
答案 1 :(得分:10)
在方法变量生命周期方面,静态和非静态方法之间没有真正的区别。在这两种情况下,作为实现细节,本地人通常(不总是:有例外)在堆栈上分配。堆栈是每线程的,因此本地方法变量不会在线程之间交叉。
实例和静态之间 here 的唯一区别是实例方法有一个隐含的第零个参数,即“this”,由调用者推送(加上一些虚拟调度和空查有趣)
为简单起见,我正在浏览迭代器块,捕获的变量等等。
答案 2 :(得分:6)
即使没有该类的实例,也存在类的所有静态成员。它们在首次使用之前的某个时间进行初始化,并在程序完成时进行清理。
如果您同时调用静态方法,则它们将使用该类的任何静态成员的相同副本(如果他们使用它们)。因此,如果静态方法对静态成员(或参数)进行操作,则应以线程安全的方式进行操作。如果静态方法仅在本地操作,则方法本身通常是线程安全的。
至于运行时如何区分两个调用者,这是线程的本质。每个线程都有自己的调用堆栈,它有自己的任何局部变量,参数,返回地址等的副本。因此,两个调用不会混淆,每个调用都会正确返回其调用者。唯一的问题是,如果静态方法对非线程安全的静态成员(或非线程安全的参数)进行操作。