2014-12-23 3 views
16

В многопоточном проекта Android, я вижу такой код:Тест слабая ссылка перед использованием Java

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

... потом где-нибудь еще:

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

Я довольно убедитесь, что между проверкой и использованием ссылки существует возможное состояние гонки, если последняя сильная ссылка на объект освобождается между двумя в другом потоке, но я не могу найти какую-либо документацию или кого-либо, кто/кто может подтвердить это лучше, чем с «вы, вероятно, правы».

Я думаю, единственно правильный способ проверить & использовать слабые ссылки делается так:

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

Я уверен, что второй метод 100% безопасен, но мне интересно, если есть некоторые Java/компилятор сахара/магии, о которых я не знаю, что сделало бы первый метод безопасным.

Итак, первый способ на 100% безопасен или нет?

+1

вы, вероятно, правы;;) – petey

+3

Не должно быть встроенного сахара/магии компилятора/магии, чтобы гарантировать, что метод №1 всегда будет работать. Ваше понимание ситуации соответствует моему пониманию ситуации. – NoseKnowsAll

+0

Спасибо за вопрос –

ответ

10

Первый метод определенно небезопасен. Каждый звонок до get является независимым. Ничто не мешает GC очистить слабодоступный объект после первых get и до второго.

В javadoc состояния

Предположим, что сборщик мусора определяет в определенный момент времени в , что объект является слабо доступным. В это время будет атомарно очистить все слабые ссылки на этот объект и все слабые ссылки на любые другие недостижимые объекты, из которых можно достичь объекта через цепочку сильных и мягких ссылок.

Это может быть в любой момент времени. Вызов get(), который (потенциально) толкает ссылку на объект в стеке, временно делает объект сильно доступным (он находится в стеке потока), но эта способность к достижению исчезает, когда заканчивается сравнение с null. После этого момента GC может определить, что объект слабо доступен, и очистить его ссылку. Тогда вы получите NullPointerException.

Используйте свой второй метод. Но учтите, что, назначив его переменной, вы делаете ссылочный объект сильно доступным.

Смежные вопросы