Zgodnie z zaleceniami innych, Interlocked.Increment
będą miały lepszą wydajność niż lock()
. Wystarczy spojrzeć na IL i Assembly, gdzie zobaczysz, że Increment
zmienia się to w instrukcję „bus lock”, a jej zmienna jest bezpośrednio zwiększana (x86) lub „dodawana” do (x64).
To polecenie „bus lock” blokuje magistralę, aby uniemożliwić innemu procesorowi dostęp do magistrali, podczas gdy wywołujący procesor wykonuje swoją operację. Teraz spójrz na lock()
IL instrukcji C # . Tutaj zobaczysz wezwania Monitor
do rozpoczęcia lub zakończenia sekcji.
Innymi słowy, lock()
instrukcja .Net robi o wiele więcej niż .Net Interlocked.Increment
.
Więc jeśli wszystko, co chcesz zrobić, to inkrementować zmienną, Interlock.Increment
będzie szybsza. Przejrzyj wszystkie metody Interlocked, aby zobaczyć różne dostępne operacje atomowe i znaleźć te, które odpowiadają Twoim potrzebom. Użyj, lock()
gdy chcesz wykonywać bardziej złożone rzeczy, takie jak wiele powiązanych ze sobą przyrostów / dekrementów lub serializować dostęp do zasobów, które są bardziej złożone niż liczby całkowite.
Sugeruję użycie wbudowanego inkrementacji blokady .NET w bibliotece System.Threading.
Poniższy kod zwiększy długość zmiennej przez odniesienie i jest całkowicie bezpieczny dla wątków:
Źródło: http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
źródło
Spróbuj z Interlocked.Increment
źródło
Jak już wspomniano, użyj
Interlocked.Increment
Przykład kodu z MS:
Poniższy przykład określa, ile liczb losowych z zakresu od 0 do 1000 jest wymaganych do wygenerowania 1000 liczb losowych z wartością punktu środkowego. Aby śledzić liczbę wartości punktu środkowego, zmienna midpointCount jest ustawiana na 0 i zwiększana za każdym razem, gdy generator liczb losowych zwraca wartość punktu środkowego, aż osiągnie 10000. Ponieważ trzy wątki generują liczby losowe, metoda Increment (Int32) jest wywoływana w celu zapewnienia, że wiele wątków nie aktualizuje współbieżnie midpointCount. Należy zauważyć, że blokada jest również używana do ochrony generatora liczb losowych i że obiekt CountdownEvent jest używany w celu zapewnienia, że metoda Main nie zakończy wykonywania przed trzema wątkami.
Poniższy przykład jest podobny do poprzedniego, z tą różnicą, że używa klasy Task zamiast procedury wątku do generowania 50 000 losowych liczb całkowitych punktu środkowego. W tym przykładzie wyrażenie lambda zastępuje procedurę wątku GenerateNumbers, a wywołanie metody Task.WaitAll eliminuje potrzebę stosowania obiektu CountdownEvent.
https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked.increment?view=netcore-3.0
źródło