开发者

Clarification of role of CSingleLock and the sync object it uses

I'm confused by the example given by Leo Davidson in is Ccriticalsection usable in production?. Leo gives three code blocks introduced as "Wrong (his example)", "Right", and "Even better (so you get RAII)".

After dismissing the first block as "Wrong", Leo acknowledges later that this is something that can occur if a function that obtains a lock calls another function which obtai开发者_如何转开发ns the same lock. Fine - there is a real danger here to avoid, and the example is not so much "wrong" as an easy trap to fall into through careless programming.

But the second and third examples confuse me completely... because we have one sync object (the CCriticalSection crit) which is used for two CSingleLock locks... implying that crit is not a lockable thing at all, but only the mechanism which does the locking for an independent object or objects. The trouble is, there is a comment saying "crit is unlocked now" right at the end... which contradicts that implication. Also... other comments qualify themselves by the need to test IsLocked()... when in my understanding, the CCriticalSection cannot timeout, and will only ever return if IsLocked() is TRUE.

The Microsoft documentation I have scanned is really not clear about what role the CSyncObject plays and the CSingleLock or CMultiLock plays. That's my main concern. Can anyone point to documentation that definitively says you can create two locks using a single sync object as Leo has suggested here?


After dismissing the first block as "Wrong", Leo acknowledges later that this is something that can occur if a function that obtains a lock calls another function which obtains the same lock. Fine - there is a real danger here to avoid, and the example is not so much "wrong" as an easy trap to fall into through careless programming.

The "wrong" first block is always wrong and should never be something you do, whether explicitly or by accident. You cannot use a CSingleLock to obtain multiple locks at the same time.

As its name suggests, CSingleLock is an object which manages one lock on one synchronization object. (The underlying synchronization object may be capable of being locked multiple times, but not via just a single CSingleLock.)

I meant that the other two code-blocks were situations you could run into legitimately.

You never need to lock the same CCriticalSection if you already have a lock on it (since you only need one lock to know you own the object), but you may lock it multiple times (usually as a result of holding the lock, then calling a function which gets the lock itself in case it is called by something that doesn't already have it). That's fine.

But the second and third examples confuse me completely... because we have one sync object (the CCriticalSection crit) which is used for two CSingleLock locks... implying that crit is not a lockable thing at all, but only the mechanism which does the locking for an independent object or objects.

You can lock a CCriticalSection directly (and multiple times if you want to). It has Lock and Unlock methods for doing that.

If you do that, though, you have to ensure that you have matching Unlock calls for every one of your Lock calls. It can be easy to miss one (especially if you use early returns or exceptions where an Unlock later in a function may be bypassed entirely).

Using a CSingleLock to lock a CCriticalSection is usually better because it will release the lock it holds automatically when it goes out of scope (including if you return early, throw an exception or whatever).

Can anyone point to documentation that definitively says you can create two locks using a single sync object as Leo has suggested here?

Although I couldn't find the source, CCriticalSection (like most MFC objects) is almost certainly a very thin wrapper around the Win32 equivalent, in this case CRITICAL_SECTION. The documentation on EnterCriticalSection tells you:

After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection or TryEnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns. The thread enters the critical section each time EnterCriticalSection and TryEnterCriticalSection succeed. A thread must call LeaveCriticalSection once for each time that it entered the critical section.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜