Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “锁定”(监视器)在.NET中是如何工作的?_C#_.net_Multithreading_Locking_Monitor - Fatal编程技术网

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。剩下的问题是:它是否可能存在我们可以创建多个同步表,尽管我认为这是不可能的。