简体   繁体   English

为什么我可以锁定C#中的任何对象类型?

[英]Why can I lock on any object type in C#?

Can someone explain, in detail, why it's possible to lock on objects of any type in C#? 有人可以详细解释为什么可以在C#中lock任何类型的对象?

I understand what lock is for and how to use it. 我理解lock是什么以及如何使用它。 I know how it expands to Monitor.Enter / Exit . 我知道它如何扩展到Monitor.Enter / Exit What I'm looking for an explanation of the implementation detail and design considerations. 我正在寻找实施细节和设计考虑因素的解释。

First of all: What is happening under the hood? 首先:引擎盖下发生了什么? For example: are there extra bits in an object instance (like there is for RTTI/vtable) that make it work? 例如:对象实例中是否有额外的位(就像RTTI / vtable那样)是否有效? Or some kind of lookup table keyed on object references? 或者在对象引用上键入某种查找表? (If so, how does this interact with the GC?) Or something else? (如果是这样,它如何与GC交互?)或其他什么? Why don't I have to create an instance of a specific type to hold whatever the lock data is? 为什么我不必创建一个特定类型的实例来保存锁定数据?

(And, by the way, what do Enter and Exit map to in native code?) (顺便说一下, EnterExit在本机代码中映射到什么?)

And, secondly, why is .NET designed to not have a specific type for taking out locks on? 其次, 为什么 .NET设计为没有特定类型来取出锁定? (Given that you generally just make a new object() for the purpose anyway - and most cases where you lock "any old object" are problematic.) Was this design choice forced by the implementation detail? (鉴于您通常只为此目的创建一个new object() - 大多数情况下您锁定“任何旧对象”都是有问题的。)这个设计选择是否被实现细节所迫? Or was it deliberate? 还是故意的? And, if deliberate, was it a good choice? 而且,如果是故意的,这是一个不错的选择吗? (I realise this second part may require speculation.) (我意识到第二部分可能需要推测。)

It is possible to lock on all non struct types. 可以lock所有非struct类型。 In layout of each refernce type on the heap there is special field (sync block) that is used to manage lock. 在堆上的每个引用类型的布局中,存在用于管理锁的特殊字段(同步块)。 The layout is covered in details in How CLR Creates Runtime Object . CLR如何创建运行时对象详细介绍了布局。 Excerpt from article is below: 文章摘录如下:

The OBJECTREF does not point to the beginning of the Object Instance but at a DWORD offset (4 bytes). OBJECTREF不指向对象实例的开头,而是指向DWORD偏移量(4个字节)。 The DWORD is called Object Header and holds an index (a 1-based syncblk number) into a SyncTableEntry table. DWORD称为Object Header,它将索引(基于1的syncblk编号)保存到SyncTableEntry表中。

Object layout on the heap: 堆上的对象布局:

sync block index 
pointer to type
fields...

Speculation part: I believe that original guidance was to lock on whatever is convinient, but it was relatively quickly changed to having special "private object for lock" due to ease of getting external code to deadlock your methods. 推测部分:我认为最初的指导是锁定任何方便的东西,但由于容易获得外部代码使你的方法陷入僵局,因此它被相对快速地改为拥有特殊的“私有锁定对象”。 I think there even were classes in Framework that were impelented with locking on publically visible objects... 我认为甚至框架中的类都被锁定在公开可见的对象上...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM