2014-12-23 14 views
16

In un progetto Android multithread, sto vedendo codice come questo:prova un riferimento debole prima di utilizzarlo java

final WeakReference<MyClass> myClassObjectWeakRef = 
       new WeakReference<MyClass>(aMyClassObject); 

... poi qualche altra parte:

if (myClassObjectWeakRef.get() != null) { 
    myClassObjectWeakRef.get().someMethod(); 
} 

Sono abbastanza certo c'è una possibile condizione di competizione tra il controllo e l'uso del riferimento, se l'ultimo riferimento forte all'oggetto viene rilasciato tra i due in un altro thread, ma non riesco a trovare alcuna documentazione o qualcuno che/chi può confermare questo meglio che con un "probabilmente hai ragione".

penserei l'unico modo giusto per testare & utilizzare un riferimento debole è fatto in questo modo:

MyClass myObject = myClassObjectWeakRef.get(); 
// we now have a strong reference, or null: standard checks apply. 
if (myObject != null) { 
    myObject.someMethod(); 
} 

Sono molto fiducioso che il secondo metodo è sicuro al 100%, ma mi chiedo se non v'è un po 'di Java/Compilatore zucchero/magia che non conosco, che renderebbe il primo metodo sicuro.

Quindi, il primo metodo è sicuro al 100% o no?

+1

probabilmente hai ragione, ;-) – petey

+3

Non ci dovrebbe essere alcun java/compiler sugar/magic integrato per garantire che il metodo # 1 funzioni sempre. La tua comprensione della situazione corrisponde anche alla mia comprensione della situazione. – NoseKnowsAll

+0

Grazie per la domanda –

risposta

10

Il primo metodo è sicuramente pericoloso. Ogni chiamata a get è indipendente. Non c'è nulla che impedisca al GC di cancellare l'oggetto debolmente raggiungibile dopo il primo get e prima del secondo.

I javadoc stati

Supponiamo che il garbage collector determina ad un certo punto nel tempo che un oggetto è debolmente raggiungibile. A quel tempo sarà cancellare atomicamente tutti i riferimenti deboli a quell'oggetto e tutti i deboli riferimenti a qualsiasi altro oggetto debolmente raggiungibile dal quale l'oggetto è raggiungibile attraverso una catena di riferimenti forti e morbidi.

Questo può essere in qualsiasi momento. Chiamando get(), che (potenzialmente) spinge un riferimento all'oggetto sullo stack temporaneamente rende l'oggetto fortemente raggiungibile (è su una pila di thread), ma quell'abilità di raggiungimento scompare nel momento in cui termina il confronto con null. Dopo quel momento, il GC può determinare che l'oggetto è debolmente raggiungibile e cancellare il suo riferimento. Otterrai quindi uno NullPointerException.

Usa il tuo secondo metodo. Ma nota che assegnandolo a una variabile, stai rendendo l'oggetto di riferimento facilmente raggiungibile.

Problemi correlati