Потокобезопасность примера Java с использованием WeakReference - PullRequest
3 голосов
/ 17 июня 2011

Я читаю о слабых ссылках в Java после того, как прочитал SO сообщение и понял, что на самом деле не знаю, что это было.

Следующий код взят из стр. 457, Глава 17: «Сборка мусора».и память "в" Языке программирования Java, четвертое издание "Арнольда, Гослинга и Холмса

import java.lang.ref.*;
import java.io.File;

class DataHandler {
    private File lastFile;        // last file read
    private WeakReference<byte[]> 
                         lastData;// last data (maybe)

    byte[] readFile(File file) {
        byte[] data;

        // check to see if we remember the data
        if file.equals(lastFile) {
            data = lastData.get();
            if (data != null)
                return data;
        }

        // don't remember it, read it in
        data = readBytesFromFile(file);
        lastFile = file;
        lastData= new WeakReference<byte[]>(data);
        return data;
    }
}

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

data = lastData.get();
if (data != null)
    return data;

Я думаю так: «данные» ограничены потоками и настроены на ссылку на референт WeakReference «lastData».Это создает сильную ссылку на референт, поэтому даже если после нулевой проверки все другие сильные ссылки на референт за пределами области действия readFile исчезают (каков правильный термин?), И даже если предположить, что референт не доступен мягко, сборщик мусора непозволил очистить слабую ссылку, тем самым делая референт финализируемым, потому что по-прежнему существует локальная сильная ссылка на него из данных.Следовательно, если данные не являются нулевыми в строке data != null, они не могут быть нулевыми при возврате в следующей строке.Правильно?

Ответы [ 3 ]

2 голосов
/ 17 июня 2011

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

Использование слабой ссылки хорошо, именно по той причине, на которую вы указали: код создает сильную ссылку, которая содержится в переменной data. Таким образом, GC не может собирать байты, и, таким образом, WeakReference останется нетронутым; поэтому использование этого кода в однопоточном приложении должно быть безопасным. Проблемы приходят с несколькими потоками:

Доступ к полям file и lastData не синхронизирован, поэтому нет гарантии, что два потока, работающие с методом readFile(..), вообще взаимодействуют (что маловероятно) лучший случай). Важно отметить, что к этим полям нужно обращаться атомарно, и если нет другого места, где они бы касались, самым простым решением было бы объявить метод readFile синхронизированным. Это очень сильно ухудшит производительность, потому что чтение файла будет происходить внутри синхронизированного блока, что может привести к серьезному конфликту.

2 голосов
/ 17 июня 2011

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

0 голосов
/ 17 июня 2011

Технически говоря, это не потокобезопасно, потому что lastData и lastFile не являются энергозависимыми.Для второго потока возможно видеть старую копию этих ссылок.Это может не иметь большого значения для вашего приложения.

...