2014-10-22 3 views
0

У меня есть два класса SomeService и Dependency настроен и подключен через Spring:Можно ли воспроизвести ошибку видимости?

@Named 
public class SomeService implements Service 
{ 

    @Inject 
    public Dependency dependency; 

    public void execute() 
    { 
     dependency.execute(); 
    } 
} 



@Named 
public class Dependency 
{ 
    public void execute() 
    { 

    } 
} 

В некоторых редких случаях SomeService.execute() бросает NPE. Я думаю, что эта проблема не является конечным/энергонезависимым полем, к которым невозможно получить доступ из разных потоков без внешней синхронизации. Довольно очевидное решение состоит в том, чтобы сделать поле «Зависимость» окончательным и заменить инъекцию поля инжектором конструктора. Но я пытался воспроизвести исходную ошибку на моей локальной машине, используя один поток, инициирующий ApplicationContext и несколько других потоков, пытающихся получить SomeService. Во всех случаях зависимость никогда не была нулевой. Возможно ли даже сделать тестовый пример, воспроизводящий проблему? Спасибо заранее.

+0

Во-первых, вы можете сделать 'зависимым' поле' private'. Я предполагаю, что вы либо устанавливаете его как «null», либо создаете экземпляр «Service» без использования зависимости ('new SomeService') в другом месте. Сделайте поле 'private' и создайте конструктор не по умолчанию (не создавайте без параметров) и проверьте, что больше не компилируется. – SJuan76

+0

Это всего лишь краткий пример реальных классов. В поле реального класса является private, а класс SomeService создается с использованием org.springframework.beans.factory.BeanFactory # getBean (java.lang.Class ). –

+0

Вы также можете использовать инъекцию конструктора, чтобы сделать их окончательными. – rlegendi

ответ

0

Ошибки параллелизма, подобные этому, иногда трудно воспроизвести на однопроцессорном оборудовании с момента, в течение которого ядро ​​см.. Различные значения в ячейках памяти являются короткими из-за общих кэшей (L3). На многопроцессорном серверном оборудовании это может быть проще, так как время синхронизации памяти по узлам больше. Это также ограничивает масштабируемость на больших машинах. Если вы разрабатываете и тестируете на небольших машинах, но работаете на большом железе, это сильно вас укусит.

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

Таким образом, вы можете увидеть его проще/чаще на многопроцессорном оборудовании, но, конечно, нет никакой гарантии.

+0

Хорошо, спасибо вам, я просто задавался вопросом, есть ли хороший способ воспроизвести такие проблемы. –