我在生产中遇到了这个代码,我觉得这可能会给我们带来麻烦.
internal static readonly MyObject Instance = new MyObject();
Run Code Online (Sandbox Code Playgroud)
两次调用Instance字段将返回具有相同哈希码的两个对象.这些物体有可能不同吗?
我对CLI的了解表明它们是相同的,因为哈希码是相同的.
有人可以澄清吗?
是的,它是安全的 - 最简单的安全单例实现.
作为比较哈希码以推断"它们是同一个对象"的另一点; 因为我们在这里谈论引用类型(单例对于值类型没有意义),检查两个引用是否指向同一对象的最佳方法是:
bool isSame = ReferenceEqual(first, second);
Run Code Online (Sandbox Code Playgroud)
这不依赖于GetHashCode()/ Equals/ ==实现(它查看引用本身).
CLR提供的保证即使多个线程使用该类,它也能正常工作.这在Ecma 335,Partition II,10.5.3.3节中规定:
当类型初始化发生在多线程系统中时,存在类似但更复杂的问题.在这些情况下,例如,两个单独的线程可能会开始尝试访问不同类型(A和B)的静态变量,然后每个线程都必须等待另一个完成初始化.
确保上述第1点和第2点的算法的概要如下:
1.在类加载时(因此在初始化时间之前)将零或null存储到该类型的所有静态字段中.
2.如果类型已初始化,则表明您已完成.
2.1.如果尚未初始化类型,请尝试进行初始化锁定.
2.2.如果成功,请记录此线程负责初始化类型并继续执行步骤2.3.
2.2.1.如果不成功,请查看此线程或等待此线程完成的任何线程是否已保持锁定.
2.2.2.如果是这样,返回,因为阻塞会造成死锁.此线程现在将看到该类型的未完全初始化状态,但不会出现死锁.
2.2.3如果不是,则阻止直到类型初始化然后返回.
2.3初始化基类类型,然后初始化此类型实现的所有接口.
2.4执行此类型的类型初始化代码.
2.5将类型标记为已初始化,释放初始化锁定,唤醒等待此类型初始化的任何线程,然后返回.
要明确的是,这是他们为CLR实现而不是代码提出的算法.
| 归档时间: |
|
| 查看次数: |
328 次 |
| 最近记录: |