Неизменяемые объекты в многопоточном приложении - как это работает? - PullRequest
5 голосов
/ 24 июля 2011

У меня этот код будет работать в многопоточном приложении. Я знаю, что неизменный объект является потокобезопасным, потому что его состояние не может быть изменено. И если у нас есть изменчивая ссылка, если она изменена, например, с помощью MyImmutableObject state = MyImmutableObject.newInstance (oldState, newArgs); то есть, если поток хочет обновить состояние, он должен создать новый неизменный объект, инициализируя его старым состоянием и некоторыми новыми аргументами состояния), и это будет видно всем другим потокам. Но вопрос в том, что если поток2 начинает длительную операцию со состоянием, в середине которого поток1 обновляет состояние новым экземпляром, что произойдет? Thread2 будет использовать ссылку на старое состояние объекта, то есть будет использовать несовместимое состояние? Или thread2 увидит изменение, сделанное thread1, потому что ссылка на состояние является изменчивой, и в этом случае thread1 может использовать в первой части своей длительной операции старое состояние, а во второй части - новое состояние, что неверно?

State state = cache.get(); //t1 
Result result1 = DoSomethingWithState(state); //t1 
        State state = cache.get(); //t2
    ->longOperation1(state); //t1
        Result result2 = DoSomethingWithState(state); //t2
             ->longOperation1(state); //t2
   ->longOperation2(state);//t1
cache.update(result1); //t1 
             ->longOperation2(state);//t2
        cache.update(result2);//t2

Result DoSomethingWithState(State state) {
    longOperation1(state);
    //Imaging Thread1 finish here and update state, when Thread2 is going to execute next method
    longOperation2(state);
return result;
}

class cache {
     private volatile State state = State.newInstance(null, null);

    update(result) {
        this.state = State.newInstance(result.getState, result.getNewFactors);

    get(){
       return state;
    }

 }

Ответы [ 2 ]

1 голос
/ 24 июля 2011

Но ссылка volatile, не делает ли она видимым новое состояние объекта ... другим потокам?

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

1 голос
/ 24 июля 2011

То, что вы описываете, не является потокобезопасным, несмотря на то, что вы используете неизменяемые объекты. thread2 продолжает воздействовать на объект, на который он изначально ссылался, даже если thread1 одновременно присваивает новое значение state. В Java ссылки на объекты передаются по значению . Поэтому, когда передается аргумент state для DoSomethingWithState() или longOperation1(), метод видит только переданную ссылку на объект, а не изменяющиеся значения позже. Если вы хотите, чтобы этот тип кода был потокобезопасным, вам нужно синхронизировать все методы, которые работают с одноэлементным state объектом.

...