Почему Interlocked.CompareExchange не работает? - PullRequest
1 голос
/ 24 апреля 2020
if (Interlocked.CompareExchange(ref this.popcount, this.popcount + 1, this.popcount) == this.popcount)
{
    pop = Interlocked.CompareExchange(ref head, head.next, head);
}

Я пишу код, но почему-то он работает не так, как я хотел ...

Interlocked.CompareExchange(ref this.popcount, this.popcount + 1, this.popcount)

Я думаю, это означает

  1. go до this.popcount укажите и получите значение popcount
  2. сравните значение с this.popcount
  3. , если оно одинаковое, добавьте 1 к this.popcount

Я не прав? Если я не прав, как я могу это исправить?

1 Ответ

2 голосов
/ 24 апреля 2020

Вам нужно запомнить значение, которое вы добавили от 1 до , значение «до», и вы не можете полагаться (пере) читать его из переменной, которую вы собираетесь изменить. Потому что весь смысл в том, что несколько потоков конкурируют за обновление значения этой переменной. Итак, вы хотите что-то вроде:

var oldcount = this.popcount;
var newcount = oldcount + 1;

if(Interlocked.CompareExchange(ref this.popcount, newcount, oldcount) == oldcount)
{
    //It worked
}
else
{
    //Loop round, try again, whatever you plan to do when you don't succeed.
}

В вашем примере, даже если CompareExchange успешно, вы сравниваете старое значение (возвращаемое CompareExchange) с новым значением (которое вы недавно Прочтите this.popcount справа от ==), и вряд ли они когда-либо совпадут. И наоборот, они могут быть равны, если ваш вызов CompareExchange действительно не удался.


Конечно, если вы просто увеличиваете переменную, Interlocked.Increment будет более подходящим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...