Ответ
Использование synchronized блоков для атомарных операций:
synchronized(lockObject) {
// critical section
}
Применение атомарных классов из java.util.concurrent.atomic:
AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet();
Использование потокобезопасных коллекций:
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
Применение volatile для переменных, которые изменяются одним потоком, а читаются другими:
private volatile boolean flag;
Использование ThreadLocal для хранения переменных, уникальных для каждого потока:
ThreadLocal<Integer> threadId = new ThreadLocal<>();
Использование высокоуровневых примитивов из java.util.concurrent:
CountDownLatchCyclicBarrierSemaphoreExchanger