Wir haben eine Methode, die den globalen Sequenzindex aller Ereignisse in unserer Anwendung verwaltet. Wie es die Website ist, wird erwartet, dass diese Methode threadsicher ist. Thread-sichere Implementierung wurde nach:Interlocked.Increment und Rückgabe des inkrementierten Werts
private static long lastUsedIndex = -1;
public static long GetNextIndex()
{
Interlocked.Increment(ref lastUsedIndex);
return lastUsedIndex;
}
Allerdings bemerkten wir, dass unter gewissen nicht schwere Last dupliziert Indizes in System erschien. Ein einfacher Test zeigte, dass es etwa 1500 Duplikate für 100000 Iterationen gibt.
public static long GetNextIndex()
{
return Interlocked.Increment(ref lastUsedIndex);
}
Allerdings verstehe ich nicht klar, warum erste Implementierung funktionierte nicht:
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)}");
}
}
Dies kann mit folgenden Umsetzung festgelegt werden. Kann mir jemand helfen zu beschreiben, was in diesem Fall passiert?
Da 'lastUsedIndex' durch einen weiteren Aufruf von' Interlocked.Increment' zwischen dem Abrufen des Ergebnisses und dem Zurücksenden an den Aufrufer aktualisiert werden könnte. –
Standard Threading Race Bug, ein anderer Thread kann die Variable auch vor 'return lastUsedIndex' inkrementieren: 'Kleine Chancen, nicht Null. Der Code liest '[read modify write] read. Die Atomicity-Garantie, die Sie von Interlocked erhalten, gilt nur für die Operationen in den Klammern. Sie müssten 'lock [read modify write read]' verwenden, um es sicher zu machen. –
RB, Hans Passant, verstanden. Kann jemand von euch es bitte als Antwort schreiben, damit es vollständig beantwortet wird? –