How would you design a Java application that needs to handle concurrent access to a shared resource?

When multiple threads access the same resource simultaneously, the application must ensure data consistency, thread safety, and high performance. A well-designed concurrent application protects shared resources from race conditions while minimizing contention and maximizing throughput.

Key Points: • Use synchronization mechanisms such as synchronized, ReentrantLock, or ReadWriteLock to control access to shared resources. • Prefer thread-safe collections like ConcurrentHashMap and CopyOnWriteArrayList when multiple threads access shared data. • Minimize the scope of locks and use concurrent utilities from the java.util.concurrent package to improve scalability.

Example: Consider an online banking system where multiple users can deposit or withdraw money from the same account. Without proper synchronization, concurrent updates may lead to incorrect balances. By protecting account operations with locks, only one thread can modify the balance at a time.

Code Example:

import java.util.concurrent.locks.ReentrantLock;

public class BankAccount {

    private double balance;
    private final ReentrantLock lock =
            new ReentrantLock();

    public void deposit(
            double amount) {

        lock.lock();

        try {

            balance += amount;

        } finally {

            lock.unlock();
        }
    }

    public double getBalance() {

        return balance;
    }
}

Best Practices: • Use ExecutorService instead of manually creating threads. • Prefer ConcurrentHashMap for shared key-value storage. • Use AtomicInteger, AtomicLong, or AtomicReference for atomic operations. • Avoid excessive locking to prevent bottlenecks. • Consider ReadWriteLock when reads are more frequent than writes. • Design immutable objects whenever possible.

Interview Tip: A concise interview answer is: To handle concurrent access to a shared resource, I use synchronization mechanisms such as synchronized blocks, ReentrantLock, or concurrent collections. I minimize lock contention, use thread-safe data structures, and leverage the java.util.concurrent package to ensure data consistency, thread safety, and scalability.