Immutable objects are not something specific to multi-threading. Any object, the state of which can not be changed after they are created (to be precise it only means the internal state of object governed by the instance variables and not any references to the object itself) is called immutable. Since, thread-safe code is something that *changes* modifies shared data in a way that even if the operations are inter-leaved, it never ever leaves the data in an inconsistent state, immutable objects do not require synchronization as they do not change.
Volatile is a weaker mode of synchronization and is effective in cases where no code follow a "check and act" semantics on the variable. Since JDK5, the AtomicXXX classes extends the concept of volatile variables to provide methods to atomically change variable values.
For more information you can follow the link Edward has pointed. [ January 25, 2008: Message edited by: Nitesh Kant ]