The java.util.concurrent package has a whole range of classes that can be used to make multi-threaded code thread-safe without explicitly using the "synchronized" keyword, if that's what you're asking.
The ThreadLocal class may also help, as may the "volatile" keyword.
And, most fundamentally, multi-threadedness is only a problem if there is shared, mutable state. If you can avoid that, then the code is multithread-safe.
Ping & DNS - updated with new look and Ping home screen widget
I faced this question while going through an interview!
If only this question ever comes up on any interview that I ever go to....
Synchronization is for a type of locking called "pessimistic locking". It is based on the theory that if you don't protect the code, the threads will step on each other and corrupt the data.
This question is perfect to go into the theory of "optimistic locking" -- how you code with the assumption that the threads won't step on each other. This can lead to how you code something to be done in an atomic fashion, and how you can use the CAS methods of the atomic classes to do so. In other words, you use separate variables to do all the operations without exposing interim data -- then use the CAS to swap the data atomically. A CAS failure is considered a collision which will trigger a rollback (and/or retry).
This question is also perfect for a discussions about transactions -- and commit and rollbacks.