Многопоточное приведение без знака С#

Я хочу увеличить число без знака из нескольких потоков.

Я знаю о Interlocked.Increment, но он не обрабатывает целые числа без знака. Я мог бы использовать lock(), но я бы предпочел, если это возможно по соображениям производительности.

Действительно ли это потокобезопасно, просто чтобы увеличить его обычным способом? Не имеет значения, потерялся ли случайный прирост, поскольку он использовался только для статистики. То, что я не хочу, - это значение, которое нужно испортить.

Ответ 2

Вы говорите, что не хотите использовать lock по соображениям производительности, но протестировали ли вы его? Неоспоримый замок (который, скорее всего, будет звучать) довольно дешев.

Я обычно предпочитаю "явно правильную", а не "умную и, возможно, лучшую работу", когда речь идет о потоковом (и вообще, но особенно для потоковой передачи).

Контролируйте свое приложение с блокировкой и без него, и посмотрите, можете ли вы даже заметить разницу. Если блокировка делает существенную разницу, то уверенность, используйте хитрую вещь. В противном случае, я бы просто придерживался блокировки.

Одна вещь, которую вы, возможно, захотите сделать, это использовать Interlocked.Increment с int и просто придать ее при необходимости, чтобы получить uint, например:

using System;
using System.Reflection;
using System.Threading;

public class Test
{
    private static int count = int.MaxValue-1;

    public static uint IncrementCount()
    {
        int newValue = Interlocked.Increment(ref count);
        return (uint) newValue;
    }

    public static void Main()
    {
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
    }

}

Вывод:

2147483647
2147483648
2147483649

(Другими словами, он обертывает без проблем.)

Ответ 3

Если вам действительно нужен полный диапазон unsigned int (2 ^ 32 - 1), а не подписанный int (2 ^ 31 -1), вы можете использовать его для int64 (есть перегрузка Interlocked.Increment, которая принимает int64), а затем вернитесь к unsigned int.