C# “锁定”(监视器)在.NET中是如何工作的?
我最近一直在想,C# “锁定”(监视器)在.NET中是如何工作的?,c#,.net,multithreading,locking,monitor,C#,.net,Multithreading,Locking,Monitor,我最近一直在想,lock(或者更具体地说:Monitor)如何在.NET内部对锁定的对象起作用。具体来说,我想知道开销是什么,如果使用了“全局”(进程)锁,如果是这种情况(对于监视器组),是否可以创建更多的全局锁,以及传递给锁的对象会发生什么情况(它们似乎不会引入额外的内存开销) 为了澄清我没有问的问题:我在这里没有问a是什么(我在大学里自己做了一个)。我也不是在问如何使用锁、监视器、如何编译成try/finally等等;我非常清楚这一点(还有其他一些与此相关的问题)。这是关于监视器的内部工作。
lock
(或者更具体地说:Monitor
)如何在.NET内部对锁定的对象起作用。具体来说,我想知道开销是什么,如果使用了“全局”(进程)锁,如果是这种情况(对于监视器组),是否可以创建更多的全局锁,以及传递给锁的对象会发生什么情况(它们似乎不会引入额外的内存开销)
为了澄清我没有问的问题:我在这里没有问a是什么(我在大学里自己做了一个)。我也不是在问如何使用锁
、监视器、如何编译成try/finally等等;我非常清楚这一点(还有其他一些与此相关的问题)。这是关于监视器的内部工作。输入和监视器。退出
例如,考虑这个代码由十个线程执行:
for (int i=0; i<1000; ++i)
{
lock (myArray[i])
{
// ...
}
}
for(inti=0;i)是阅读显示器、内存屏障等的好地方
编辑
如果页面在将来关闭,则从页面截图:
Monitor.Enter
不是一个正常的.NET方法(无法使用ILSpy或类似工具进行反编译)。该方法是由CLR内部实现的,因此严格来说,.NET没有一个答案,因为不同的运行时可以有不同的实现
NET中的所有对象都有一个对象头,其中包含指向对象类型的指针,还有一个SyncBlock
索引到SyncTableEntry
。通常该索引为零/未使用,但当锁定对象时,它将包含一个索引到SyncTableEntry
,该索引随后包含对实际对象的引用锁定对象
因此,锁定数千个对象确实会创建大量锁,这是一种开销
我在这篇MSDN文章中找到了这些信息:你应该添加一些来自该网站的信息,以防该页面将来不可用。这一点很好,thx。事实上,我已经看到了该页面,因为我记得:我不确定我知道你问什么。对象用作“锁”是对引用类型的简单引用。对象内部的内容无关紧要。Monitor.Enter
将查看所讨论的引用是否在其已持有的“锁”集合上。如果是,它将阻止线程,直到引用可用。如果锁可用/变为可用,它将被获取(放入该引用集合中),并一直保存到Monitor.Exit
。在您的示例中,如果myArray
是X[]
类型,其中X
是引用类型(即不是结构或枚举类型),这很好。这取决于块内的内容。另请参阅,您应该根据需要将其锁定。lock
如果出现需要1000个锁的情况,请继续。为不同的目的制作一个锁可能与拥有多个锁一样糟糕,而您只需要一个锁。lock
实现确实是您需要的不必担心。你为什么要干预它?创建你自己的低级锁机制的可能原因是什么?@Sinatr好吧,在大多数情况下,这不是“需要”,而是一个选择的问题,不是吗?如果你必须做出选择,我想最好了解底层机制并选择它正确的选择。对,这回答了我所寻找的大部分问题。我提到的全局锁是围绕SyncTableEntry
的旋转锁,内存开销约为72字节。性能开销取决于散列-假设碰撞次数非常少,这可能约为0。剩下的问题是:它是否可能存在我们可以创建多个同步表,尽管我认为这是不可能的。