Зачем использовать System.Threading.Interlocked.Decrement вместо минуса?

Я конвертировал некоторый код С# в vb.net, и converter.telerik.com сделал это:

i--;

в это:

System.Math.Max(System.Threading.Interlocked.Decrement(i), i + 1)

Что со всей фантазией?

Ответ 1

Комментарий Michał Piaskowski вызвал следующее объяснение:

Семантика i-- в С# должна вернуть текущее значение i (т.е. значение до начала декремента), а затем уменьшить i на единицу.

Итак, нам нужно преобразовать это в VB. Мы не можем использовать i -= 1, потому что это не возвращает текущее значение i до декремента. Итак, нам нужна операция, которая уменьшит i, но вернет значение i до декремента, что-то вроде:

Function DoPostDecrement(ByRef i As Integer) As Integer
    i -= 1
    Return i + 1
End Function

Но это предполагает использование следующего, чтобы избежать необходимости писать метод для выполнения вышеперечисленного:

System.Math.Max(
    someValueThatIsEqualToiMinusOne,
    someValueThatIsEqualtoiBeforeTheDecrement
)

Но VB.NET не позволит вам использовать i -= 1 или i = i - 1 вместо someValueThatIsEqualToiMinusOne. Однако System.Threading.Interlocked.Decrement(i) является допустимым и равным значению i - 1. Как только вы это сделаете, поскольку параметры оцениваются слева направо, someValueThatIsEqualtoiBeforeTheDecrement должен быть i + 1 (в этот момент декремент был выполнен до i + 1 - это значение предварительного декремента.

Обратите внимание, что приведенный выше метод DoPostDecrement и конструктор System.Math.Max, System.Threading.Interlocked.Decrement могут иметь разную семантику в многопоточном контексте.

Ответ 2

Операция с блокировкой atomic; в многопоточных контекстах вы можете безопасно использовать его, не удерживая блокировку, если вы будете осторожны.

Ответ 3

Единственная причина, по которой я вижу, - это

Interlocked.Decrement Method

Уменьшает указанную переменную и сохраняет результат, как атомный операции.

Ответ 4

Это зависит - есть ли "i" общая переменная? Это в потокобезопасной среде?

Если "i" является целым числом, то i-- делает по существу следующее (игнорируя детали):

  • вычитает один из i
  • присваивает это значение обратно i

Как вы можете видеть, есть > 1 шаг. Если "i" находится в потокобезопасном месте (статическая переменная, разделенная по потокам и т.д.), Тогда поток может потенциально остановиться в середине этих двух шагов, другой поток может выполнить оба действия, а затем вы будете иметь проблема с недопустимыми данными.

Класс Interlocked по существу объединяет два этапа выше в один шаг, обеспечивая атомную операцию. Теперь вам не нужно беспокоиться о потоках, поскольку это одна операция и не может быть прервана другим потоком.

Ответ 5

Чтобы ответить на ваш вопрос, выглядит так: converter.telerik.com вещь чрезмерно консервативна в отношении проблем с потоками. WAAAY слишком консервативен. Я вернул бы код в i--, если один и тот же экземпляр i не будет мутироваться из нескольких потоков одновременно.