Reputation: 6806
I've been using Windows CRITICAL_SECTION
since the 1990s and I've been aware of the TryEnterCriticalSection
function since it first appeared. I understand that it's supposed to help me avoid a context switch and all that.
But it just occurred to me that I have never used it. Not once. Nor have I ever felt I needed to use it. In fact, I can't think of a situation in which I would.
Generally when I need to get an exclusive lock on something, I need that lock and I need it now. I can't put it off until later. I certainly can't just say, "oh well, I won't update that data after all". So I need EnterCriticalSection
, not TryEnterCriticalSection
So what exactly is the use case for TryEnterCriticalSection
?
I've Googled this, of course. I've found plenty of quick descriptions on how to use it but almost no real-world examples of why. I did find this example from Intel that, frankly doesn't help much:
CRITICAL_SECTION cs;
void threadfoo()
{
while(TryEnterCriticalSection(&cs) == FALSE)
{
// some useful work
}
// Critical Section of Code
LeaveCriticalSection (&cs);
}
// other work
}
What exactly is a scenario in which I can do "some useful work" while I'm waiting for my lock? I'd love to avoid thread-contention but in my code, by the time I need the critical section, I've already been forced to do all that "useful work" in order to get the values that I'm updating in shared data (for which I need the critical section in the first place).
Does anyone have a real-world example?
Upvotes: 1
Views: 603
Reputation: 13689
In C++11 therestd::lock
which employs deadlock-avoidance algorithm.
In C++17 this has been elaborated to std::scoped_lock
class.
This algorithm tries to lock on mutexes in one order, and then in another, until succeeds. It takes try_lock
to implement this approach.
Having try_lock
method in C++ is called Lockable
named requirement, whereas mutexes with only lock
and unlock
are BasicLockable
.
So if you build C++ mutex on top of CTRITICAL_SECTION
, and you want to implement Lockable
, or you'll want to implement lock avoidance directly on CRITICAL_SECTION
, you'll need TryEnterCriticalSection
Additionally you can implement timed mutex on TryEnterCriticalSection
. You can do few iterations of TryEnterCriticalSection
, then call Sleep
with increasing delay time, until TryEnterCriticalSection
succeeds or deadline has expired. It is not a very good idea though. Really timed mutexes based on user-space WIndows synchronization objects are implemented on SleepConditionVariableSRW
, SleepConditionVariableCS
or WaitOnAddress
.
Upvotes: 1
Reputation: 15162
Because windows CS are recursive TryEnterCriticalSection allows a thread to check whether it already owns a CS without risk of stalling.
Another case would be if you have a thread that occasionally needs to perform some locked work but usually does something else, you could use TryEnterCriticalSection and only perform the locked work if you actually got the lock.
Upvotes: 0
Reputation: 28839
As an example you might have multiple threads that each produce a high volume of messages (events of some sort) that all need to go on a shared queue.
Since there's going to be frequent contention on the lock on the shared queue, each thread can have a local queue and then, whenever the TryEnterCriticalSection
call succeeds for the current thread, it copies everything it has in its local queue to the shared one and releases the CS again.
Upvotes: 2