我有这段代码将在多线程应用程序中工作。我知道不可变对象是线程安全的,因为它的状态无法更改。如果我们有可变引用,则用例如MyImmutableObject state = MyImmutableObject.newInstance(oldState,newArgs)进行更改。例如,如果一个线程想要更新状态,则它必须创建一个新的不可变对象,并使用旧状态和一些新的状态参数对其进行初始化),这对于所有其他线程都是可见的。但是问题是,如果一个线程2开始对该状态进行长时间操作,那么在哪个线程1中使用新实例更新该状态的情况下,将会发生什么?Thread2将使用对旧对象状态的引用,即它将使用不一致的状态吗?否则线程2将看到线程1所做的更改,因为对状态的引用是易变的,
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;
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个不变的对象,它封装在类中并且是全局状态。
可以说我有2个线程获得此状态,并执行myMethod(state)。并说thread1首先完成。它修改全局状态,调用GlobalStateCache.updateState(state,newArgs);。
GlobalStateCache {
MyImmutableState state = MyImmutableState.newInstance(null, null);
public void updateState(State currentState, Args newArgs){
state = MyImmutableState.newInstance(currentState, newArgs);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,线程1将更新缓存的状态,然后线程2进行相同的操作,它将覆盖该状态(请注意,从线程1更新的状态)
我搜索了Google,Java规范并在实践中阅读了Java并发性,但是显然没有指定。我的主要问题是,对已经读取了不可变状态的线程来说,不可变状态对象的值是否可见。我认为它不会看到更改后的状态,只有在更新后才能看到它。
所以我不明白何时使用不可变对象?这是否取决于我在我看到的最新状态下是否可以进行并发修改并且不需要更新状态?