2013-04-21 8 views

risposta

9

Una differenza molto importante è che i metodi compareAndSet e weakCompareAndSet hanno semantica diversa per AtomicReference<Integer> rispetto a AtomicInteger. Questo perché con AtomicReferece<Integer>, questi metodi usano == per il confronto e due oggetti Integer possono essere uguali senza essere ==. Con AtomicInteger, il confronto è dell'uguaglianza del valore intero, non dell'identità di riferimento.

Come altri hanno sottolineato, AtomicInteger ha funzionalità aggiuntive non disponibili con AtomicReference<Integer>. Inoltre, AtomicInteger estende Number, quindi eredita tutti i metodi Number (doubleValue(), ecc.) E può essere utilizzato ogni volta che è previsto un Number.

+1

Vale la pena sottolineare anche che gli oggetti interi auto-boxed nell'intervallo da -127 a 128 sono internati e che il loro == restituirà true mentre i numeri interi al di fuori di questo intervallo non lo saranno. Gli interi creati con 'new Integer (3)' ovviamente non avranno la stessa identità. Questo può causare ogni sorta di comportamenti sorprendenti. –

+0

@ JedWesley-Smith - Punto eccellente. Secondo l'API, anche i valori al di fuori dell'intervallo _might_ possono essere memorizzati nella cache. Quindi, per peggiorare le cose, i "comportamenti sorprendenti" possono essere diversi su diverse piattaforme Java. –

+0

Esatto, si tratta di un hack non documentato su cui non si dovrebbe fare affidamento. –

6

AtomicReference è una classe generica che può fare riferimento a tipi arbitrari.
Se si desidera utilizzare un'istanza della propria classe atomicamente, è necessario AtomicReference<V>.

AtomicInteger è una versione specializzata che contiene numeri interi. È più efficiente (senza inutili boxe) e ha metodi utili come incrementAndGet().

+1

Inoltre, due oggetti 'Integer' possono essere uguali senza essere identici. –

8

Non molta differenza se si utilizza solo set(...) e get() ma il AtomicInteger ha alcuni altri metodi come incrementAndGet() che funzionano solo per i numeri interi.

Il AtomicReference avvolge un volatile Object mentre AtomicInteger avvolge una volatile int modo che possa fare metodi numero intero compreso specifici incremento, decremento, e aggiungere metodi. AtomicInteger estende anche Number che significa che supporta i metodi doubleValue(), longValue(), ecc.

+1

perché non ha ottenuto il segno di spunta verde? Vernebelt? :) –

2

Come indicato da altri, AtomicReference<Integer> utilizza == per confrontare gli oggetti. Pertanto, compareAndSet(expect, update) aggiornerà il riferimento iniziale solo se expect è uguale all'oggetto memorizzato nel riferimento di riferimento atomico utilizzando ==.

Può causare alcuni bug insidiosi se si utilizza AtomicReference per tipi numerici, ad esempio Integer o Long. Si noti che i costruttori statici di tali classi (ad esempio, Integer.valueOf(int value)) restituiscono oggetti memorizzati nella cache per valori piccoli. In altre parole, due chiamate diverse a Integer.valueOf(5) restituiscono la stessa istanza di Integer. È sicuro, poiché le classi sono immutabili. Nel risultato, se si utilizza AtomicReference<Integer> mentre si dovrebbe usare davvero AtomicInteger, potrebbe funzionare bene per questi piccoli numeri, perché == potrebbe effettivamente confrontare gli stessi oggetti. Diventa peggio solo quando inizi a gestire valori più alti ad un certo punto.

Riassumendo, utilizzando AtomicInteger è molto più sicuro per operazioni numerico :)

+0

Vedere il commento sulla risposta di Ted Hopp, l'internamento degli oggetti Integer avviene solo per un set limitato, non per tutti. Affidarsi all'internamento per rendere il lavoro == è considerato dannoso in quanto non documentato e potrebbe cambiare. –

+0

Bene, questo è ciò che intendevo per "piccoli valori". Non volevo specificare l'intervallo, poiché potrebbe essere soggetto a modifiche. La mia conclusione è stata esattamente quello che stai dicendo: non dovresti mai fare affidamento su == per lavorare con oggetti numerici. – dah4ns

Problemi correlati