你是对的。volatile 提供了可见性保证。synchronized 提供可见性保证和受保护代码段的序列化。对于非常简单的情况,volatile 就足够了,但是使用 volatile 而不是同步很容易遇到麻烦。
如果您假设 Account 有调整余额的方法,那么 volatile 还不够好
public void add(double amount)
{
balance = balance + amount;
}
那么如果余额不稳定而没有其他同步,我们就会遇到问题。如果两个线程尝试一起调用 add() ,则可能会出现“错过”更新,其中会发生以下情况
Thread1 - Calls add(100)
Thread2 - Calls add(200)
Thread1 - Read balance (0)
Thread2 - Read balance (0)
Thread1 - Compute new balance (0+100=100)
Thread2 - Compute new balance (0+200=200)
Thread1 - Write balance = 100
Thread2 - Write balance = 200 (WRONG!)
显然这是错误的,因为两个线程都读取当前值并独立更新,然后将其写回(读取、计算、写入)。volatile 在这里没有帮助,因此您需要同步以确保一个线程在另一个线程开始之前完成整个更新。
我一般发现,如果在编写一些代码时我认为“我可以使用 volatile 而不是同步”,答案很可能是“是”,但是确定它的时间/精力以及出错的危险是不值得的利益(次要表现)。
顺便说一句,一个编写良好的 Account 类将在内部处理所有同步逻辑,因此调用者不必担心它。