Java 多线程应用程序中的不可变对象-它是如何工作的?

Java 多线程应用程序中的不可变对象-它是如何工作的?,java,multithreading,object,concurrency,immutability,Java,Multithreading,Object,Concurrency,Immutability,我有这个代码将在多线程应用程序工作。 我知道不可变对象是线程安全的,因为它的状态不能更改。如果我们有易失性引用,则if随。 MyImmutableObject状态=MyImmutableObject.newInstance(oldState,newArgs);i、 如果一个线程想要更新状态,它必须创建新的不可变对象(用旧状态和一些新状态参数初始化它),这对所有其他线程都是可见的。 但问题是,如果线程2开始与状态长时间的操作,在THeLe1以新实例更新状态的中间,会发生什么?Thread2将使用对

我有这个代码将在多线程应用程序工作。 我知道不可变对象是线程安全的,因为它的状态不能更改。如果我们有易失性引用,则if随。 MyImmutableObject状态=MyImmutableObject.newInstance(oldState,newArgs);i、 如果一个线程想要更新状态,它必须创建新的不可变对象(用旧状态和一些新状态参数初始化它),这对所有其他线程都是可见的。 但问题是,如果线程2开始与状态长时间的操作,在THeLe1以新实例更新状态的中间,会发生什么?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;
    }

 }

您描述的不是线程安全的,尽管您使用的是不可变对象
thread2
继续作用于它最初获得引用的对象,即使
thread1
同时指定了
state
的新值。在java中,对象引用是按值传递的。因此,当传递
DoSomethingWithState()
longOperation1()
state
参数时,该方法只会看到传递的对象引用,而不会看到以后更改的值。如果希望此类代码是线程安全的,则需要同步作用于singleton
state
对象的所有方法

但是引用是volatile的,它不是使新的对象状态对其他线程可见吗


否。当每次后续读取
volatile
字段时,另一个线程必须重新读取该字段以获得新值

但是引用是易失性的,它是否使新的对象状态(易失性引用所指向的状态)对其他线程可见。@dimitar:在java中,对象引用是按值传递的。这意味着
DoSomethingWithState()
获取对象引用的副本。如果在此之后更改另一个作用域中的引用,
DoSomethingWithState()
不受影响。是的,我知道,它会将缓存引用更改为指向ne对象值,DoSomethingWithState中引用的副本仍将指向旧对象值。所以volatile引用并不总是100%对所有线程可见,只对重新读取状态的线程可见。那么,保持线程安全的最佳方法是什么呢,因为我不想让不同的线程在不同的状态下工作。请不要交叉张贴如何实现这一点?我对这个问题的理解不够透彻,无法提出正确的解决方案。我不清楚长操作之间有什么关系,也不清楚为什么有两个线程,也不清楚这对
update()
一个不可变对象意味着什么。假设我有一个进程执行器,它必须使用共享状态,并最终在完成后对其进行修改。每个进程都在新线程中启动,进程逻辑是无状态的,状态缓存在内存缓存中。每个进程都在基于状态进行一些工作。根据状态,流程逻辑可以解决不同的情况,这些情况的结果是状态的新更新。完成流程逻辑后,我从当前状态和结果构建新的不可变对象。然后,您必须同步对共享状态的访问。请看。在本例中,我可以运行两个线程来执行流程逻辑,它们都获得最新的不可变状态,但最后完成的线程只会覆盖另一个线程的更改。两个线程都不会看到另一个线程的更改,即使引用是volatile的,这基本上意味着对volatile私有属性的访问是轻量级同步。任何复制的引用都不会看到对私有属性的更改。