synchronized works, but it cannot time out or try once and give up, and it is heavy for a single counter. ReentrantLock adds tryLock, timeouts and fairness, while atomic classes like AtomicInteger update one variable safely without locks. Use an atomic for counters and flags, and a lock when several fields must change together. If synchronized already fits, keep it, since a lock must always be released in finally.