我们有一个方法可以维护应用程序中所有事件的全局序列索引。由于它是网站,因此预计会有这种方法线程安全。线程安全的实现如下:
private static long lastUsedIndex = -1;
public static long GetNextIndex()
{
Interlocked.Increment(ref lastUsedIndex);
return lastUsedIndex;
}
但是我们注意到,在一些不重负载下,系统中会出现重复索引。简单的测试表明,对于 100000 次迭代,大约有 1500 个重复项。
internal class Program
{
private static void Main(string[] args)
{
TestInterlockedIncrement.Run();
}
}
internal class TestInterlockedIncrement
{
private static long lastUsedIndex = -1;
public static long GetNextIndex()
{
Interlocked.Increment(ref lastUsedIndex);
return lastUsedIndex;
}
public static void Run()
{
var indexes = Enumerable
.Range(0, 100000)
.AsParallel()
.WithDegreeOfParallelism(32)
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.Select(_ => GetNextIndex())
.ToList();
Console.WriteLine($"Total values: {indexes.Count}");
Console.WriteLine($"Duplicate values: {indexes.GroupBy(i => i).Count(g => g.Count() > 1)}");
}
}
这可以通过以下实现来解决:
public static long GetNextIndex()
{
return Interlocked.Increment(ref lastUsedIndex);
}
但是,我不清楚,为什么第一次实施没有奏效。任何人都可以帮我描述在这种情况下发生了什么吗?