多线程调用synchronized修饰的deposit方法时,balance需设volatile吗?
在多线程环境下调用deposit时,无需将balance声明为volatile
先看你给出的多线程调用代码:
new Thread(() -> { for (int i = 0; i < 100000000; i++) { account1.deposit(1); } }, "t1").start(); new Thread(() -> { for (int i = 0; i < 100000000; i++) { account1.deposit(1); } }, "t2").start();
以及对应的同步账户类:
class BankAccountSynchronized { private long balance; public BankAccountSynchronized(long balance) { this.balance = balance; } public synchronized void deposit(long amount) { balance += amount; } public long getBalance() { return balance; } }
核心结论:不需要给balance加volatile
原因很简单,synchronized已经同时解决了可见性和原子性问题,完全覆盖了volatile的作用:
- 可见性保障:进入
synchronized方法时,线程会丢弃本地缓存的balance值,强制从主内存读取最新数据;退出方法时,会把修改后的balance立即刷回主内存,确保其他线程能拿到最新值。 - 原子性保障:
balance += amount是"读取-修改-写入"的复合操作,volatile管不了这种操作的原子性,但synchronized会把整个方法变成原子操作,避免多线程同时修改导致的数值错乱。
额外注意点
当前代码里的getBalance方法没有加同步,这会导致其他线程调用它时,可能读到的是本地缓存里的旧余额。如果要保证余额读取的准确性,建议给getBalance也加上synchronized修饰。
内容的提问来源于stack exchange,提问作者Jack Ma
相关产品推荐
相关产品推荐

