gpt4 book ai didi

c#:Monitor.Wait是如何实现的?

转载 作者:行者123 更新时间:2023-11-30 20:28:56 26 4
gpt4 key购买 nike

C#的system.threading.monitor类中的Monitor.Wait()方法是如何实现的?

https://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified

从概念上讲,我设想的是这样的:

   class Monitor {
public static Wait(object o)
{
// Release Lock
Monitor.Exit(o);

// Spinlock until another Thread acquires Lock
while(!Monitor.isEnter(o));

// Wait to re-acquire lock
Monitor.Enter(o);
}
}

有这么准吗?还是我遗漏了什么?

这是我考虑作为前面代码基础的典型监视器类示例。

using System.Threading;

readonly object o = new object();

// In Thread #1: (Where appropriate)
lock(o) {
Monitor.Wait(o);
}

//In Thread #2: (Where appropriate)
lock(o) {
Monitor.Pulse(o);
}

Lock(o) 当然是内置的 c# 快捷方式:

try {
Monitor.Enter(o);
{
//Lock Block Here
}
}
finally {
Monitor.Exit(o);
}

最佳答案

要真正了解是否有更简单的方法来实现 Monitor.Wait,我们必须调查其在低级别的功能。实际的实现最终是用 C 语言编写的,对我们是隐藏的,但专门针对 Monitor.Wait(object),我们可以通过以下方式跟踪调用链;

Monitor.Wait(o)
-- return Monitor.Wait(o, -1, false)

Monitor.Wait(o, -1, false)
-- Monitor.ObjWait(false [exitContext], -1 [millisecondsTimeout], o)

从这里开始,即使在 ILSpy 中也很难看到发生了什么。根据 Tigran 到 Monitor 对象源的链接,我们在源中留下了以下内容;

    /*========================================================================
** Waits for notification from the object (via a Pulse/PulseAll).
** timeout indicates how long to wait before the method returns.
** This method acquires the monitor waithandle for the object
** If this thread holds the monitor lock for the object, it releases it.
** On exit from the method, it obtains the monitor lock back.
** If exitContext is true then the synchronization domain for the context
** (if in a synchronized context) is exited before the wait and reacquired
**
** Exceptions: ArgumentNullException if object is null.
========================================================================*/
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj)

关于它在做什么以及以什么顺序进行的描述是相当不言自明的。然而,它这样做的精确实现是从各种包含关键代码的 private static extern 方法包装的。

外部 specifies实际的实现在于另一个程序集。它可以在访问非托管代码时与 DllImport 一起使用(这里不是这种情况)或者可以是 extern alias .从这里按照 SO post asking about where to find the implementation of extern methods ,您必须查看 C 代码本身,它可以在 Core CLR 中找到(信贷斯科特张伯伦)。

从这里我们可以看到 ObjWait() 的 C 方法实现 maps (第 1027 行)到 CLR 中的 ObjectNative::WaitTimeout

FCIMPL3(FC_BOOL_RET, ObjectNative::WaitTimeout, CLR_BOOL exitContext, INT32 Timeout, Object* pThisUNSAFE)
{
FCALL_CONTRACT;

BOOL retVal = FALSE;
OBJECTREF pThis = (OBJECTREF) pThisUNSAFE;
HELPER_METHOD_FRAME_BEGIN_RET_1(pThis);

if (pThis == NULL)
COMPlusThrow(kNullReferenceException, W("NullReference_This"));

if ((Timeout < 0) && (Timeout != INFINITE_TIMEOUT))
COMPlusThrowArgumentOutOfRange(W("millisecondsTimeout"), W("ArgumentOutOfRange_NeedNonNegNum"));

retVal = pThis->Wait(Timeout, exitContext);

HELPER_METHOD_FRAME_END();
FC_RETURN_BOOL(retVal);
}
FCIMPLEND

在进入这个之前,值得一看 this (也归功于 Scott Chamberlain),其中指出;

FCalls are identified in managed code as extern methods with the MethodImplOptions.InternalCall bit set.

这解释了我们到 ObjWait()ObjectNative::WaitTimeout 的链接。因此,进一步分解它,我们可以看到基本的 null 和参数检查,如果是这样的话会引发适当的异常。症结在于对 pThis->Wait() 的调用...在这一点上我无法进一步追踪...还没有。

从这里我们到达Object::Wait(line 531),然后转到SyncBlock::Wait(line 3442)。至此,我们已经掌握了大部分实现内容,而且还有很多。

考虑到以上所有内容并回到您所要求的更简单的实现,我对简化 Monitor.Wait() 持谨慎态度。引擎盖下发生了很多事情,很容易犯错并在替代实现中产生潜在错误。

编辑

严肃的大喊Scott Chamberlain谁在 ILSpy 级别下进行了大部分调查并深入研究/调试 C 代码堆栈。几乎所有 ILSpy 级别以下的调查工作都是他的,我只是在这里将其编译成一个答案。

关于c#:Monitor.Wait是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46797381/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com