With following class,
// This class should be thread-safe!!!
class BankAccount {
private long balance; // Should it be volatile?
synchronized void deposit(long amount) {
// ...
balance += amount;
}
synchronized void withdraw(long amount) {
// ...
balance -= amount;
}
}
Should I add volatile
to balance
field?
No, compared with
synchronized
keyword,volatile
is lightweight.volatile
can gurantee the reader thread always get freshbalance
value, but it can not makebalance += amount;
atomic.synchronized
can do both.You don’t need
volatile
in the code shown, because the variable is used only within thesynchronized
methods. Thesynchronized
methods make sure that the variable’s contents are visible and not stale, and also make sure that the operations performed within eachsynchronized
method are not interfered with by concurrently running threads. Thevolatile
keyword is redundant here, it only makes sure the variable’s contents are visible.If you want the variable’s value to be visible to threads that don’t enter a
synchronized
instance method on this object (maybe you’d like it to be used in methods that don’t acquire a lock on the instance), then in that case keeping itvolatile
would make sense.If you took away the
synchronized
keywords and left the variablevolatile
, you’d have a problem, because althoughvolatile
makes sure updates are visible it doesn’t make sure the updates are atomic. The+=
and-=
operations here are not atomic and can be interfered with by concurrently-running threads.Alternatively consider using an
AtomicLong
instead, in this example you might not need thesynchronized
keyword (depending on what the code in //... does). Methods likeaddAndGet
perform their changes to the value stored atomically. For most things where you would have used volatile before, the Atomic classes can do a better job.