javamultithreadingrace-conditiondata-race

Java multithread race condition, Min and Max range of a value


I have been asked this question recently in an interview, and I didn't get a feedback from my interviewer. I think the minimum answer is 2.

Given the following code, what will be the minimum and maximum value that will be printed in the line marked with 3 black '*'

import java.util.List;

public class Main {

    public static final int THREAD_NUMBER = 10;
    public static Integer num = 0;
    final static Integer lock = 0;

    public static void main(String[] args) throws InterruptedException {

        Thread threads[] = new Thread[THREAD_NUMBER];

        for (int j = 0; j < THREAD_NUMBER; j++) {
            int finalJ = j;
            threads[j] = new Thread(() -> {threadLogic(finalJ);});
            threads[j].start();
        }

        for (int j = 0; j < THREAD_NUMBER; j++) {
            threads[j].join(); //todo add catch exception
        }

***        System.out.println("********* The number is " + num + " *********");
***    }

    public static void addOne(int id){
        // Critical Code
        synchronized (lock) {
            num = num + 1;
            System.out.println("add action thread " + id + ": " + num);
        }
    }

    public static void multiTwo(int id){
        // Critical Code
        synchronized (lock) {
            num = num * 2;
            System.out.println("multi action thread " + id + ": " + num);
        }
    }

    public static void threadLogic(int id){
            addOne(id);
            multiTwo(id);
    }
}

I tried running the code myself and got 2046 for the max number


Solution

  • Theoretically, it is possible that each thread will be interrupted after it executed addOne() so that multiTwo() is executed first after all threads have run addOne(). This would mean

    10 * 2^10 = 10240

    as the result.

    If each thread will execute addOne() immediately followed by multiTwo(), the result is the already mentioned 2046.

    On a modern PC, the latter option is the most likely, but on a first generation Raspi that runs tons of other (unrelated) stuff at the same time, you may get something that resembles the first option at least partially – but only when Thread::start does not cause an immediate context switch to the new Thread.