You have a critical section of code that accesses a shared resource. How would you manage access to this section to avoid concurrency issues?

When multiple threads access a shared resource, proper synchronization is required to prevent race conditions, inconsistent data, and corruption. Access to the critical section should be controlled so that only one thread can modify the shared resource at a time while maintaining data integrity and application stability.

Key Points: • Synchronization mechanisms such as synchronized blocks, ReentrantLock, and semaphores can be used to protect critical sections. • Proper locking ensures that only one thread accesses the shared resource at a given moment, preventing concurrent modification issues. • Modern concurrency utilities from java.util.concurrent often provide better scalability and flexibility than traditional synchronization.

Example: Consider a banking application where multiple threads attempt to withdraw money from the same account simultaneously. Without synchronization, the account balance could become inconsistent. By protecting the withdrawal logic with a lock, only one thread can update the balance at a time.

Code Example:

class BankAccount {

    private int balance = 10000;

    public synchronized void withdraw(int amount) {

        if (balance >= amount) {

            balance -= amount;

            System.out.println(

Thread.currentThread().getName() + " withdrew " + amount + ", Remaining Balance: "

                    + balance);
        }
    }
}

public class Main {

    public static void main(String[] args) {

        BankAccount account =
                new BankAccount();

        Runnable task =
                () -> account.withdraw(1000);

        new Thread(task, "Thread-1").start();
        new Thread(task, "Thread-2").start();
    }
}

Interview Tip: A concise interview answer is: To protect a critical section, I use synchronization mechanisms such as synchronized, ReentrantLock, or other concurrency utilities. These ensure controlled access to shared resources, prevent race conditions, and maintain data consistency in multithreaded applications.