Java 并发性:我是否必须同步一个只检索状态而不修改状态的方法?

Java concurrency : Do I have to synchronise a method that only retrieve state and does not modify it?

我正在学习 java 并发性并使用了多人共享的银行账户示例来尝试实践并发性原则。

这是我的帐户class。

public class Account(){
    private int balance = 0;

    public int getBalance(){ return balance}              
    public synchronized void deposit(int val){//..}   
    void synchronized void withdrawal(int val){//..}
}

存款和取款方法是同步的,因为它们直接修改帐户对象的状态,以避免多个用户同时尝试更改它时数据损坏。

另一方面,getBalance() 不会更改 Account 对象的状态。但我在想,如果在存款或取款时调用 getBalance(),它将 return 一个过时的值。什么是标准做法,同步还是不同步getBalance()

恕我直言,当您尝试修改 属性 时,需要同步以避免 'race condition'。 https://netjs.blogspot.com/2015/06/race-condition-in-java-multi-threading.html

因此,如果您正在修改它,您可以预测结果。否则,您无法保证输出结果。

除此之外,我可能会将余额 属性 包装到某个 AtomicInteger 中,或者至少将其标记为易失性。

您需要同步一个对象而不是文字,因为只同步对于比函数更好的性能至关重要的对象。

Object lock = new Object();

      public class Account(){
        private int balance = 0;

        public int getBalance(){ synchronized (lock){return balance} }              
        public void deposit(int val){synchronized (lock){...}  }   
        void withdrawal(int val){synchronized (lock){...}  }
      }
    }

通过这种方式,您可以在函数内添加更多逻辑,以更好地执行并在更新时保持平衡同步。

if getBalance() is called while a deposit or withdrawal is happening, it will return the outdated value

没有过时的值,而这些进程是 运行,只是因为您不能确定它们是否会失败(我假设您没有使用 balance 中间状态表示字段)。

所以问题实际上是 - 你是否想读取最近的余额状态并在取款或存款是 运行 的情况下执行此操作?或者,您想等到其中一个进程完成,以便读取值?

在第一种情况下,您可以简单地使该字段可变 (private volatile int balance = 0;) 以确保线程之间的内存可见性。
在第二种情况下,只需使用 synchronized.