开发者

tricky InterlockedDecrement vs CriticalSection

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.


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.


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.


Yes, you do.

Otherwise it could be that:

  1. The value is read

  2. The value is incremented atomically

  3. 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. :)

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜