问题描述
命名空间 MyNameSpace{静态类 MyClass{静态 MyClass(){//认证过程..用户需要输入密码}public static void MyMethod(){//依赖于构造函数的成功完成}}课程计划{静态无效主(字符串 [] args){MyClass.MyMethod();}}}
这是我假设的顺序
- 静态构造函数的开始
- 静态构造函数结束
- main 开始
- MyMethod 开始
- 主要内容结束
现在在任何情况下,如果 4 将在 2 之前开始,我就完蛋了.可能吗?
你在这里只问了一个问题,但你应该问了十几个问题,所以我会回答它们全部.
这是我假设的顺序
- 类构造函数的开始(也称为
cctor
) - 编码器结束
- 开始主程序
- MyMethod 开始
这是正确的吗?
没有.正确的顺序是:
- 程序的 cctor 的开始,如果有的话.没有.
- 程序的结尾,如果有的话.没有.
- 主程序开始
- MyClass 的 cctor 开始
- MyClass 的控制器结束
- MyClass.MyMethod 的开始
如果有静态字段初始值设定项怎么办?
在某些情况下,允许 CLR 更改静态字段初始值设定项的运行顺序.有关详细信息,请参阅 Jon 在该主题上的页面:
是否有可能在该类的 cctor 完成之前调用像 MyMethod
这样的静态方法?
是的.如果 cctor 本身调用 MyMethod 那么显然 MyMethod 将在 cctor 完成之前被调用.
cctor 不调用 MyMethod.是否有可能在 MyClass 的 cctor 完成之前调用像 MyMethod
这样的静态方法?
是的.如果 cctor 使用另一种类型,其 cctor 调用 MyMethod,则 MyMethod 将在 MyClass cctor 完成之前被调用.
没有ccctors直接或间接调用MyMethod!现在是否有可能在 MyClass 的 cctor 完成之前调用像 MyMethod
这样的静态方法?
没有
即使涉及多个线程也是如此吗?
是的.在可以在任何线程上调用静态方法之前,cctor 将在一个线程上完成.
cctor 可以被多次调用吗?假设两个线程都导致 cctor 运行.
无论涉及多少线程,cctor 都保证最多被调用一次.如果两个线程同时"调用 MyMethod,则它们会竞争.其中一个输掉比赛并阻塞,直到 MyClass cctor 在获胜线程上完成.
丢失的线程阻塞,直到 cctor 完成?真的吗?
真的.
那么,如果 获胜 线程上的 cctor 调用阻止 失败 线程先前占用的锁的代码怎么办?
然后你就有了一个经典的锁顺序反转条件.你的程序死锁了.永远.
这看起来很危险.如何避免死锁?
如果这样做会很痛,那么停止这样做.永远不要做会阻塞控制器的事情.
依靠 cctor 初始化语义来强制执行复杂的安全要求是一个好主意吗?有一个负责用户交互的 cctor 是个好主意吗?
都不是好主意.我的建议是您应该找到一种不同的方法来确保满足您的方法的影响安全的先决条件.
namespace MyNameSpace
{
static class MyClass
{
static MyClass()
{
//Authentication process.. User needs to enter password
}
public static void MyMethod()
{
//Depends on successful completion of constructor
}
}
class Program
{
static void Main(string[] args)
{
MyClass.MyMethod();
}
}
}
Here is the sequence which I assumed
- Start of static constructor
- End of static constructor
- Start of main
- Start of MyMethod
- End of main
Now in any scenario if 4 will start before 2 I am screwed. Is it possible?
You only asked one question here but there are a dozen or so questions that you should have asked, so I'll answer them all.
- Start of class constructor (also known as
cctor
) - End of cctor
- start of Main
- start of MyMethod
No. The correct sequence is:
- Start of cctor for Program, if there is one. There is not.
- End of cctor for Program, if there is one. There is not.
- Start of Main
- Start of cctor for MyClass
- End of cctor for MyClass
- Start of MyClass.MyMethod
The CLR is permitted to change the order in which static field initializers run in some cases. See Jon's page on the subject for details:
The differences between static constructors and type initializers
Yes. If the cctor itself calls MyMethod then obviously MyMethod will be called before the cctor completes.
Yes. If the cctor uses another type whose cctor calls MyMethod then MyMethod will be called before the MyClass cctor completes.
No.
Yes. The cctor will finish on one thread before the static method can be called on any thread.
The cctor is guaranteed to be called at most once, no matter how many threads are involved. If two threads call MyMethod "at the same time" then they race. One of them loses the race and blocks until the MyClass cctor completes on the winning thread.
Really.
Then you have a classic lock order inversion condition. Your program deadlocks. Forever.
If it hurts when you do that then stop doing that. Never do something that can block in a cctor.
Neither are good ideas. My advice is that you should find a different way to ensure that the security-impacting preconditions of your methods are met.
这篇关于静态构造函数如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!