Потоки и синхронизация - PullRequest
0 голосов
/ 29 июля 2010

У меня проблемы с пониманием следующего фрагмента кода: -

public class SoCalledSigleton{

    private final static boolean allDataLoaded = SoCalledSigleton();

    private SoCalledSigleton(){

         loadDataFromDB();
         loadDataFromFile();
         loadDataAgainFromDB();

    }    
}

Безопасен ли этот фрагмент кода? Если нет, то почему?

Ответы [ 5 ]

5 голосов
/ 29 июля 2010

Это создаст ошибку в Java.

private final static boolean allDataLoaded = SoCalledSigleton();
  • Вы присваиваете объект логической переменной.
  • Вы забыли добавить new для создания экземплярапеременная.

Но если ваш код подобен этому

 public class SoCalledSigleton{

    private final static SoCalledSigleton allDataLoaded = new SoCalledSigleton();

    private SoCalledSigleton(){

         loadDataFromDB();
         loadDataFromFile();
         loadDataAgainFromDB();

    }    
}

Он поточно-ориентирован, так как статическая инициализация и статические атрибуты поточно-ориентированы.Они инициализируются только один раз и существуют на протяжении всего жизненного цикла системы.

2 голосов
/ 29 июля 2010

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

Какой открытый интерфейс будут использовать пользователи для получения экземпляра синглтона?

2 голосов
/ 29 июля 2010

(я предполагаю, что allDataLoaded означает SoCalledSigleton, а boolean - просто опечатка: -)

Если у класса нет других конструкторов или методы loadData*Не занимайтесь забавными делами (такими как публикация this), его инициализация является поточно-ориентированной, потому что инициализация конечных элементов статических данных защищена JVM.Такие члены инициализируются загрузчиком классов при первой загрузке класса.При этом существует блокировка класса, поэтому процесс инициализации является потокобезопасным, даже если несколько потоков пытаются получить доступ к классу параллельно.Таким образом, конструктор класса гарантированно будет вызываться только один раз (для загрузчика классов - спасибо Visage за разъяснения: -).

Обратите внимание, что поскольку вы не показываете нам остальную часть класса (я полагаюдолжен иметь хотя бы метод static getInstance и, возможно, дополнительные нестатические члены), мы не можем ничего сказать о том, является ли целая реализация класса поточно-безопасной или нет.

0 голосов
/ 29 июля 2010

Из того, что мы видим , нет особых проблем - гарантируется, что конструктор будет вызываться только один раз (поэтому по определению не может быть многопоточным), что, я полагаю, является тем, что вы были обеспокоены.

Тем не менее, есть еще возможные области для проблем. Во-первых, если методы loadData... являются общедоступными, то они могут быть вызваны кем угодно в любое время, что вполне может привести к ошибкам параллелизма.

Кроме того, эти методы предположительно модифицируют какую-то коллекцию. Если эти коллекции общедоступны до того, как конструктор вернется, вы можете легко столкнуться с проблемами параллелизма. Это может быть проблемой с любым исключением, обновляющим специфичные для экземпляра поля (статические поля могут отображать или не отображать эту проблему в зависимости от того, где они определены в файле).

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

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

Полагаю, я пытаюсь сказать, что вам нужно подумать и понять, как используется класс. Показывать снимок половины файла (который даже не компилируется) и просить их дать ответ «да» или «нет» не принесет пользы. В лучшем случае они укажут некоторые проблем для вас, если они есть; в худшем случае вы получите ложное чувство уверенности.

0 голосов
/ 29 июля 2010

Да, это потокобезопасно. «Метод» - это конструктор, и он будет вызываться при загрузке класса, т. Е. Ровно один раз.

Но, глядя на то, что делается, я думаю, что это, наверное, паршивая идея - вызывать его из загрузчика классов. По сути, вы в конечном итоге будете выполнять подключение к БД и все такое в тот момент, когда что-то в вашем коде коснется SoCalledSingleton. Скорее всего, это не будет в какой-то четко определенной последовательности событий, где, если есть ошибка, у вас есть блоки catch, чтобы привести вас к некоторой полезной обработке сообщений GUI или что-то еще.

"Чистый" способ - использовать метод synchronized static getInstance(), который создаст ваш класс и вызовет его код именно тогда, когда getInstance() вызывается в первый раз.

РЕДАКТИРОВАТЬ: Как указал Elite Gentleman, там есть синтаксическая ошибка. Вы должны сказать

private final static SoCalledSingleton allDataLoaded = new SoCalledSigleton();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...