我对Leo Davidson在is Ccriticalsection usable in production?中给出的例子感到困惑。 Leo给出了三个代码块:“错误(他的例子)”,“正确”和“更好(所以你得到RAII)”。
在将第一个块解除为“错误”之后,Leo稍后承认,如果获得锁的函数调用另一个获得相同锁的函数,则会发生这种情况。很好 - 这里有一个真正的危险要避免,而且这个例子并不像通过粗心的编程容易陷入的那样“错误”。
但是第二个和第三个例子完全让我感到困惑...因为我们有一个同步对象(CCriticalSection暴击)用于两个CSingleLock锁...意味着暴击根本不是一个可锁定的东西,而只是对独立对象进行锁定的机制。麻烦的是,有一条评论说“暴击现在正在解锁”......这与这种暗示相矛盾。另外......其他评论通过测试IsLocked()的必要性来确定...在我的理解中,CCriticalSection不能超时,并且只有在IsLocked()为TRUE时才会返回。
我扫描的Microsoft文档实际上并不清楚CSyncObject扮演的角色以及CSingleLock或CMultiLock扮演的角色。这是我的主要关注点。任何人都可以指出文档明确表示你可以使用单个同步对象创建两个锁,正如Leo在这里建议的那样?
答案 0 :(得分:1)
解雇第一个街区后 “错了”,利奥后来承认 如果是,这可能会发生 获取锁定调用的函数 另一个获得的功能 同样的锁。很好 - 有一个真实的 这里要避免的危险,以及这个例子 并不是一个容易陷阱的“错误” 通过粗心而陷入困境 编程。
“错误的”第一个块总是错误,永远不会成为你做的事情,无论是明确的还是偶然的。 无法使用CSingleLock同时获取多个锁。
顾名思义,CSingleLock是一个管理一个同步对象上的锁的对象。 (底层同步对象可能能够多次锁定,但不能仅通过一个CSingleLock锁定。)
我的意思是其他两个代码块是你可以合法地遇到的情况。
如果您已经锁定了相同的CCriticalSection,那么你永远不会需要来锁定它(因为你只需要一个锁来知道你拥有该对象),但你可能多次锁定(通常由于持有锁,然后调用一个获取锁本身的函数,以防它被一些尚未拥有它的东西调用)。没关系。
但第二和第三个例子 完全迷惑我...因为我们 有一个同步对象( 使用的CCriticalSection暴击) 对于两个CSingleLock锁...暗示 暴击不是可以锁定的东西 所有,但只有机制 锁定一个独立的对象 或对象。
您可以直接锁定CCriticalSection(如果您愿意,可以多次锁定)。它具有锁定和解锁方法。
但是,如果您这样做,则必须确保每次锁定呼叫都有匹配的解锁呼叫。可能很容易错过一个(特别是如果您使用早期返回或异常,以后可以完全绕过函数中的解锁)。
使用CSingleLock来锁定CCriticalSection通常会更好,因为它会在超出范围时释放它自动保存的锁(包括如果你提前返回,抛出异常或其他)。
任何人都可以指出文档 明确地说你可以创造两个 使用单个同步对象锁定 Leo在这里建议了吗?
虽然我找不到源代码,但CCriticalSection(与大多数MFC对象一样)几乎可以肯定是围绕Win32等效的一个非常薄的包装器,在本例中为CRITICAL_SECTION。 EnterCriticalSection上的文档告诉您:
线程拥有a的所有权后 关键部分,它可以做 额外的电话 EnterCriticalSection或 TryEnterCriticalSection没有 阻止其执行。这可以防止 一个来自死锁的线程 等待它的关键部分 已经拥有。线程进入 关键部分每次 EnterCriticalSection和 TryEnterCriticalSection成功。一个 线程必须调用LeaveCriticalSection 每次进入的时间一次 关键部分。