Blog

Java Interview: Advanced Guide & MCQs on Synchronization, Multithreading, and Concurrency for Experienced Developers

Q1. What is the result of attempting to compile and run the following Java code snippet?

final class FinalClass {
    final int finalField;
    FinalClass() {
        finalField = 10;
    }
    final void finalMethod() {
        System.out.println("Final method.");
    }
}
class Extension extends FinalClass { // Line 1
    void finalMethod() { // Line 2
        System.out.println("Attempting to override.");
    }
}
  • A) Compiles and prints “Final method.”
  • B) Compilation fails due to an attempt to extend a final class at Line 1.
  • C) Compilation fails due to an attempt to override a final method at Line 2.
  • D) Compiles and prints “Attempting to override.”

Answer: B) Compilation fails due to an attempt to extend a final class at Line 1.

Q2. Consider the following code snippet. What is the potential problem?

class Counter {
    private int count = 0;
    void increment() {
        count++;
    }
    int getCount() {
        return count;
    }
}
  • A) There is no problem with the code.
  • B) The increment the method should be synchronized to prevent race conditions.
  • C) The getCount method should return a long instead of an int.
  • D) The count variable should be marked as volatile.

Answer: B) The increment the method should be synchronized to prevent race conditions.

Q3. What does the following code print?

public class ThreadExample extends Thread {
    public void run() {
        for(int i = 0; i < 3; i++) {
            System.out.print(i + "..");
        }
    }
    public static void main(String[] args) {
        ThreadExample t = new ThreadExample();
        t.start();
        System.out.print("Done");
    }
}
  • A) 0..1..2..Done
  • B) Done0..1..2..
  • C) 0..Done1..2..
  • D) The output cannot be determined.

Answer: D) The output cannot be determined.

Q4. Which statement about the following code is true?

class BankAccount {
    private double balance;
    synchronized void deposit(double amount) {
        balance += amount;
    }
    synchronized double getBalance() {
        return balance;
    }
}
  • A) The code is not thread-safe and will result in a race condition.
  • B) The code is thread-safe and will not result in a race condition.
  • C) Only the deposit method should be synchronized.
  • D) The balance variable should be marked as volatile.

Answer: B) The code is thread-safe and will not result in a race condition.

Q5. What is the primary purpose of the ConcurrentHashMap class in Java?

  • A) To allow multiple threads to write to a map without synchronization.
  • B) To prevent all access to the map while one thread is writing.
  • C) To replace the HashMap class for better performance.
  • D) To ensure the order of elements in the map.

Answer: A) To allow multiple threads to write to a map without synchronization.

Q6. What is the result of executing the following code snippet?

public class Counter implements Runnable {
    private static int count = 0;
    public synchronized void run() {
        count++;
        System.out.println(count);
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(new Counter());
        Thread t2 = new Thread(new Counter());
        t1.start();
        t2.start();
    }
}
  • A) The program prints “1” and “2” in an unpredictable order.
  • B) The program may print “1” twice.
  • C) The program prints “1” and “2” in the order of thread execution.
  • D) Compilation fails.

Q7. Consider the following Java code snippet. What will it output?

final int[] values = {1, 2, 3};
values[0] = 10;
System.out.println(values[0]);
  • A) 1
  • B) 10
  • C) Compilation error
  • D) An exception at runtime

Answer: B) 10

Explanation: The final keyword when applied to a variable means that the reference itself cannot be changed to point to another array or object, but the contents of the array or the fields of the object can still be modified. In this case, values is a reference to an array of integers. While we cannot assign a new array to values after its declaration, we can modify the elements of the array it references. Hence, the setting values[0] = 10 is valid and the output will be “10”.

Q8. Which statement is true about the synchronized keyword in Java?

  • A) It can only be applied to methods.
  • B) It ensures that only one thread can execute a block of code at a time.
  • C) It automatically locks on the class’s this object when applied to static methods.
  • D) It increases the performance of multithreaded applications.

Answer: B) It ensures that only one thread can execute a block of code at a time.

Explanation: The synchronized keyword can be used to mark methods or blocks of code so that only one thread can access them at any given time for any given instance of a class. This is crucial for preventing race conditions when multiple threads might change the same data concurrently. It does not inherently lock on the class’s this object when applied to static methods; instead, it locks on the Class object that represents the class being synchronized if the method is static.

Q9. What is the purpose of the volatile keyword in Java?

  • A) To make the class thread-safe
  • B) To ensure that updates to a variable are propagated predictably to other threads
  • C) To lock a variable for exclusive access by a thread
  • D) To declare a variable as immutable

Answer: B) To ensure that updates to a variable are propagated predictably to other threads.

Explanation: The volatile keyword is used to indicate that a variable’s value will be modified by different threads. Declaring a variable volatile ensures that any thread that reads the variable will see the most recent write to that variable. This is a light form of synchronization, suitable for variables that are accessed by multiple threads but not involved in compound operations (like increment).

Q10. Given the following code, identify the line that could cause a race condition.

public class Counter {
    private int count = 0;
    public void increment() {
        count++; // Line 1
    }
    public int getCount() {
        return count; // Line 2
    }
}
  • A) Line 1
  • B) Line 2
  • C) Both Line 1 and Line 2
  • D) Neither Line 1 nor Line 2

Answer: C) Both Line 1 and Line 2

Explanation: A race condition can occur when multiple threads access shared data and try to change it at the same time. In this example, both the increment operation (count++) and the read operation (return count) could be involved in a race condition if they are accessed by multiple threads simultaneously without proper synchronization, leading to inconsistent views of the value of count..

Q11. Why are immutable objects considered inherently thread-safe in Java?

  • A) Because their state cannot change after construction
  • B) Because they use synchronization internally
  • C) Because they can only hold primitive data types
  • D) Because they are stored in the stack rather than the heap

Answer: A) Because their state cannot change after construction.

Explanation: Immutable objects are thread-safe because their state cannot be changed after they are constructed. This means that they can be shared between threads without the need for synchronization, as there is no risk of one thread modifying the state in a way that affects another thread.

Q12. Which Java Concurrency utility is best suited for managing a set of threads that perform various tasks asynchronously?

  • A) Volatile variables
  • B) Synchronized blocks
  • C) Executors framework
  • D) java.util.concurrent.Semaphore

Answer: C) Executors framework

Explanation: The Executors framework is part of the java.util.concurrent package and provides a higher-level replacement for working directly with threads. It is specifically designed to manage a pool of threads and execute asynchronous tasks. The framework simplifies the process of assigning tasks to threads and managing their lifecycle.

Q13. Consider the following code snippet. Which modification makes the LazyInitRace class thread-safe?

public class LazyInitRace {
    private ExpensiveObject instance = null;
    public ExpensiveObject getInstance() {
        if (instance == null)
            instance = new ExpensiveObject();
        return instance;
    }
}
  • A) Adding synchronized keyword to the getInstance() method
  • B) Declaring instance variable as volatile
  • C) Using java.util.concurrent.locks.Lock around the instance check and creation
  • D) All of the above

Answer: D) All of the above

Q14. What is the correct way to handle an interrupted exception in a thread’s run method?

  • A) Ignore the exception
  • B) Log the exception and exit the method
  • C) Re-interrupt the thread and exit the method
  • D) Throw a RuntimeException

Answer: C) Re-interrupt the thread and exit the method

Q15. Which of the following operations is atomic and does not require synchronization?

  • A) Reading and writing to a volatile long variable on a 32-bit JVM
  • B) Incrementing a long variable with ++
  • C) Setting a reference to a new object
  • D) Reading and writing to a non-volatile long variable

Answer: C) Setting a reference to a new object

Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over