Actually, lots of ways:
- No need for synchronization at all if you don't have mutable state.
- No need for synchronization if the mutable state is confined to a single thread. This can be done by using local variables or
java.lang.ThreadLocal. - You can also use built-in synchronizers.
java.util.concurrent.locks.ReentrantLockhas the same functionality as the lock you access when usingsynchronizedblocks and methods, and it is even more powerful.