Thread safety in Java can be achieved by ensuring that shared data is accessed and modified by only one thread at a time. Some common techniques to achieve thread safety include:

  • Synchronization: Use the synchronized keyword to lock methods or blocks of code, ensuring only one thread can access the critical section at a time.

  • Locks: Use explicit locks like ReentrantLock for more advanced control over thread synchronization (e.g., lock timeouts, try-lock).

  • Immutable objects: Make objects immutable so that their state cannot be changed after construction, reducing the need for synchronization.

  • Atomic operations: Use classes from java.util.concurrent.atomic (like AtomicInteger) for thread-safe operations on single variables.

  • Concurrent collections: Use thread-safe collections like ConcurrentHashMap, CopyOnWriteArrayList, etc., which handle synchronization internally.

By applying these strategies, you can ensure that your Java program is thread-safe, preventing data corruption and ensuring reliable concurrent execution.