В соответствии с рекомендациями других, производительность Interlocked.Increment
будет выше, чем у lock()
. Достаточно взглянуть на IL и Assembly, где вы увидите, что это Increment
превращается в оператор «блокировки шины», а его переменная напрямую увеличивается (x86) или «добавляется» к (x64).
Этот оператор "bus lock" блокирует шину, чтобы предотвратить доступ к ней другого ЦП, когда вызывающий ЦП выполняет свою работу. Теперь взгляните на lock()
IL в C # оператора. Здесь вы увидите звонки Monitor
, чтобы начать или закончить раздел.
Другими словами, .Net lock()
заявление делает гораздо больше, чем .Net Interlocked.Increment
.
Так что, если все, что вы хотите сделать, это Interlock.Increment
увеличить переменную, будет быстрее. Просмотрите все методы блокировки, чтобы увидеть различные доступные атомарные операции и найти те, которые соответствуют вашим потребностям. Используйте, lock()
если вы хотите сделать более сложные вещи, такие как множественные взаимосвязанные приращения / уменьшения или сериализовать доступ к ресурсам, которые являются более сложными, чем целые числа.
Я предлагаю вам использовать встроенный инкремент блокировки .NET в библиотеке System.Threading.
Следующий код будет увеличивать длинную переменную по ссылке и полностью безопасен для потоков:
Источник: http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
источник
Попробуйте с блокировкой.Инкремент
источник
Как уже упоминалось, использовать
Interlocked.Increment
Пример кода от MS:
В следующем примере определяется, сколько случайных чисел в диапазоне от 0 до 1000 требуется для генерации 1000 случайных чисел со значением средней точки. Чтобы отслеживать количество значений средней точки, переменная midpointCount устанавливается равной 0 и увеличивается каждый раз, когда генератор случайных чисел возвращает значение средней точки, пока оно не достигнет 10000. Поскольку три потока генерируют случайные числа, вызывается метод Increment (Int32), чтобы несколько потоков не обновляли midpointCount одновременно. Обратите внимание, что блокировка также используется для защиты генератора случайных чисел, и что объект CountdownEvent используется для гарантии того, что метод Main не завершит выполнение до трех потоков.
Следующий пример аналогичен предыдущему, за исключением того, что он использует класс Task вместо процедуры потока для генерации 50 000 случайных целых чисел средней точки. В этом примере лямбда-выражение заменяет процедуру потока GenerateNumbers, а вызов метода Task.WaitAll устраняет необходимость в объекте CountdownEvent.
https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked.increment?view=netcore-3.0
источник