2009-03-28 12 views
12

Czy jest jakaś różnica w rozumieniu AtomicIntegerArray i AtomicInteger[]? A który z nich jest szybszy w użyciu? (zauważyłem tylko, że pierwsze zajmuje dużo mniej miejsca, ale oznacza to, że każda ponowna kontrola sprawdza granice tablicy, co spowolniłoby działanie).AtomicIntegerArray vs AtomicInteger []

Edytuj: W scenariuszu, w którym tablica jest wstępnie zainicjowany.

Odpowiedz

8

AtomicInteger[] będzie wymagać obiektu na element. AtomicIntegerArray wymaga tylko obiektu AtomicIntegerArray i obiektu tablicy. Więc użyj tego ostatniego, jeśli to możliwe.

Koszt kontroli granicznej jest dość mały, nawet w przypadku normalnych tablic. Istotne może być to, że dostęp do danych w tej samej linii pamięci podręcznej z wielu procesorów może powodować poważne problemy z wydajnością. W związku z tym pomocne mogą być oddzielne obiekty lub umyślnie omijające bliskie elementy tablicy.

+0

Kogo obchodzi kontrola graniczna? Jeśli spojrzysz na (widoczny) kod źródłowy dla, powiedzmy, getAndSet, to robi on obliczenia adresu dla get i compareAndSet (choć gorzej niż to, większość procesorów może wykonać get-and-set bez cas). –

+0

tnx (nie widziałem twojego drugiego akapitu) Więc może być dobrze nie tworzyć wszystkich obiektów w tym samym czasie? (lub z pewną losową kolejnością?) – Sarmun

+0

(Szybko edytowałem.) Tworzenie obiektów w różnych momentach nie pomoże, ponieważ GC je przestawi. Jedna z klas w java.util.concurrent posuwa się aż do dodania wielu paddingów (w najnowszych wersjach). Powinno być łatwiejsze i bardziej przejrzyste dodawanie elementów dopełniających do AtomicIntegerArray, wystarczy przesunąć w lewo. –

0

Zgadzam się z pierwszym akapicie Tom Hawin za ...

AtomicInteger [] będzie wymagać obiekt za elementu. AtomicIntegerArray wymaga tylko obiektu AtomicIntegerArray i obiektu tablicy. Więc użyj tego ostatniego, jeśli to możliwe.

... ale należy również zauważyć, że AtomicInteger [] nie jest bezpieczny dla wątków. W szczególności odwołania tablicy do poszczególnych obiektów AtomicInteger mogą być poprawne lub nie, jeśli można uzyskać do nich dostęp z wielu wątków. Jednak synchronizacja dostępu do samego obiektu tablicowego wyeliminuje ten problem.

+2

Głównym celem Atomic * jest unikanie synchronizacji. Założona metoda użycia AtomicInteger [] polega na tym, aby utworzyć AtomicIntegers tylko raz i tylko wtedy bezpiecznie opublikować tablicę. –

+1

Zgadzam się. Nie jestem zwolennikiem używania AtomicInteger [], tylko zauważam różnicę, o co chodziło w tym pytaniu :) –

4
  • AtomicInteger [] to tablica liczb całkowitych bezpiecznych dla wątków.
  • AtomicIntegerArray to bezpieczny dla wątków zbiór liczb całkowitych.
2

Pod spodem AtomicInteger i AtomicIntegerArray zwykle używają tych samych API niskiego poziomu do wykonywania odczytów, zapisów i innych operacji CAS. (Na przykład OpenSDK 7 używa sun.misc.Unsafe do wykonywania operacji CAS w obu klasach.) W związku z tym AtomicInteger [] ma niewielką przewagę wydajności. Jak już zauważyłeś, użycie AtomicIntegerArray ma ma znaczące zalety pamięci.

Z praktycznego punktu widzenia użycie późniejszego uwalnia użytkownika od konieczności konstruowania wszystkich instancji AtomicInteger. Pamiętaj, że nie możesz naiwnie alokować tych leniwie z powodów współbieżności; będziesz musiał wstępnie przydzielić lub użyć bezpiecznego mechanizmu publikowania. Więc oprócz zalet pamięci, twój kod jest czystszy.

W podobnym tonie, jeśli masz kilka obiektów z członkami AtomicInteger, na przykład:

class ReadCounter { 
    private final String _fileName; 
    private final AtomicInteger _readCount; 
    ... 
} 

private final Map<String, ReadCounter> _counterByName = ...; 

Wtedy można osiągnąć podobną poprawę pamięci przez modelowanie zmienną składową _readCount jako volatile int i korzystania AtomicIntegerFieldUpdater.

+0

Za cenę niższej prędkości dla operacji aktualizacji (chociaż get i set są szybkie). Czasami warto przedłużyć Atomic * jako oszczędzający pamięć hack. –

Powiązane problemy