C#多线程无符号增量

Fla*_*cks 15 c# multithreading unsigned interlocked-increment

我想从多个线程递增无符号整数.

我知道Interlocked.Increment,但它不处理无符号整数.我可以使用lock(),但出于性能原因我不愿意.

它只是以正常方式增加它的线程安全吗?如果偶尔的增量丢失也没关系,因为它只用于统计.我不想要的是腐败的价值.

Jon*_*eet 41

你说你lock出于性能原因不想使用- 但你测试过了吗?一个无争议的锁(这可能是由它的声音)很便宜.

在涉及线程时(通常,特别是线程),我通常会选择"明显正确"而不是"聪明且可能更好".

使用和不使用锁定对您的应用进行基准测试,看看您是否能够注意到差异.如果锁定有显着差异,那么请确保使用狡猾的东西.否则,我只是坚持使用锁.

可能想要做的一件事就是使用Interlocked.Incrementa int并在必要时使用它来获取a 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 unchecked((uint) newValue);
    }

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

}
Run Code Online (Sandbox Code Playgroud)

输出:

2147483647
2147483648
2147483649
Run Code Online (Sandbox Code Playgroud)

(换句话说,它没有任何问题.)


Mit*_*eat 11

如果你真的需要全范围的unsigned int(2 ^ 32 - 1)而不是signed int(2 ^ 31 -1),你可以转换为int64(有一个带有int64的Interlocked.Increment重载)然后再回送到unsigned int.

  • 请注意,Interlocked.Increment(ref long)实际上只是64位操作系统下的原子(参见文档) (4认同)
  • 就个人而言,我会使用常规int来保证一般安全...如果31位不够,那么我怀疑32实际上会更好地工作,除非问题在2G和4G测量之间特别限制. (2认同)