Reputation: 8904
There is global long count
counter.
Thread A does
EnterCriticalSection(&crit);
// .... do something
count++; // (*1)
// .. do something else
LeaveCriticalSection(&crit);
Thread B does
InterlockedDecrement(&count); // (*2) not under critical secion.
At (*1), I am under a critical section. At (*2), I am not.
Is (*1) safe without InterlockedIncrement()
? (it is protected critical section).
Do I need InterlockedIncrement()
at (*1) ?
I feel that I can argue both for and against.
Upvotes: 1
Views: 2118
Reputation: 500635
Both threads should use either InterlockedDecrement
/InterlockedIncrement
, or the same critical section. There is no reason for the mixing and matching to work correctly.
Consider the following sequence of events:
Thread A: enter the critical section
Thread A: read count into a register
Thread A: increment the value in the register
Thread B: InterlockedDecrement(&count) <<< There's nothing to stop this from happening!
Thread A: write the new count
Thread A: leave the critical section
Net result: you've lost a decrement!
A useful (if deliberately simplified) mental model for critical sections is this: all entering a critical section does is prevent other threads from entering the same critical section. It doesn't automatically prevent other threads from doing other things that may require synchronization.
And all InterlockedDecrement
does is ensure the atomicity of the decrement. It doesn't prevent any other thread performing computations on an outdated copy of the variable, and then writing the result back.
Upvotes: 4
Reputation: 210563
The value is read
The value is incremented atomically
The original value is incremented and written, invalidating the previous atomic update
Furthermore, you need the same critical section for both, since it doesn't help to lock on separate things. :)
Upvotes: 1
Reputation: 19042
You should use one or the other, not mix them.
While InterlockedDecrement
is guaranteed to be atomic, operator++
is not, though in this case it likely will be depending upon your architecture. In this case, you're not actually protecting the count
variable at all.
Given that you appear to want to do simple inrecrement/decrement operations, I would suggest that you simply remove the critical section in this case and use the associated Interlocked*
functions.
Upvotes: 5