Это выглядит правильно на первый взгляд, но каждый раз, когда вы используете две взаимосвязанные операции подряд, вы подвергаете себя проблеме ABA . В этом случае один поток не может изменить его с 0xFFFF на 1 (ICX возвращает !=0xFFFF
), поэтому он идет вперед и принимает ветвь if
и увеличивает ее. Перед выполнением InterlockedIncrement
другие потоки изменяют m_ref
обратно на 0xFFFF, а исходный поток увеличивает 0xFFFF. В зависимости от типа / семантики m_ref эффект будет осторожным, но, несомненно, будет плохим.
Вы должны выполнить одну операцию ICX для 0xFFF до 1 и от X до X + 1 и всегда повторять попытку, если вы потеряли ICX:
volatile <type> m_ref;
<type> ref, newRef, icxref;
do
{
ref = m_ref;
newRef = (0xFFFF == ref) ? 1 : ++ref;
icxref = InterlockedCompareExchange (&m_ref, newRef, ref);
} while (icxref != ref);
if (newRef == 1 && ref != 0xFFFF)
{
DoSomething ();
}