有全球long count
柜台
线程A
EnterCriticalSection(&crit);
// .... do something
count++; // (*1)
// .. do something else
LeaveCriticalSection(&crit);
线程B
InterlockedDecrement(&count); // (*2) not under critical secion.
在(* 1),我处于一个关键部分。在(* 2),我不是。
没有InterlockedIncrement()
,(* 1)安全吗? (它是受保护的关键部分)
我需要InterlockedIncrement()
(* 1)吗?
我觉得我可以赞成和反对。
答案 0 :(得分:5)
你应该使用其中一种,而不是混合它们。
虽然InterlockedDecrement
保证是原子的,但operator++
不是,但在这种情况下,它可能取决于您的架构。在这种情况下,您实际上并没有实际保护count
变量。
鉴于您似乎想要进行简单的inrecrement / decrement操作,我建议您在这种情况下删除关键部分并使用相关的Interlocked*
函数。
答案 1 :(得分:4)
两个主题都应使用 <{strong> InterlockedDecrement
/ InterlockedIncrement
,或相同的关键部分。混合和匹配没有理由正常工作。
考虑以下事件序列:
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
净结果:你已经失去了减量!
关键部分的一个有用的(如果是故意简化的)心智模型是这样的:所有进入关键部分都会阻止其他线程进入相同的关键部分。它不会自动阻止其他线程执行可能需要同步的其他操作。
所有InterlockedDecrement
都确保了减量的原子性。它不会阻止任何其他线程对变量的过时副本执行计算,然后将结果写回。
答案 2 :(得分:1)
读取值
该值以原子方式递增
原始值递增并写入,使先前的原子更新无效
此外,两者都需要相同的关键部分,因为它无法锁定单独的内容。 :)