I'm learning about multi-threading in Java and was experimenting with threads. I came up with a sort of racing condition code (sort of... excuse this noob) where 2 threads work in a loop (100 times) and races to change a static variable. The goal is when a thread first completes the loop (either running in time-slicing environment or parallelly) the value of the variable is printed and system.exit(int status) is called to terminate program! This is to just find out which thread won the race!
The expected output should be: nameOfTheThreadThatWonTheRace + "--" + valueOf'I'IncrementedInTheLoop
Here is the code:
public class Nest
{
public static void main(String[] args) throws Exception
{
Thread r1 = new Thread(new Racer(),"R1");
Thread r2 = new Thread(new Racer(),"R2");
r1.start();
r2.start();
}
}
class Racer implements Runnable
{
public void run()
{
for(int i = 0; i <= 100; i++)
{
Value.value = Thread.currentThread().getName() + "--" + i;
}
Value.printValue();
System.exit(0);
}
}
class Value
{
static String value = null;
public static void printValue()
{
System.out.println(value);
}
}
However actual output is different (4 runs):
R2--100 R2--100
R2--84 R2--100
R1--100 R1--100
R2--39 R2--100
I'm at loss at why is JVM not halting after any one of the thread reaches 'System.exit(0)' line? Does exit() only shuts down main thread or entire JVM or are the still-executing-threads are stopping the JVM to halt?
Also please explain to me why 2 lines of o/p are being produced?
For extra info:
Processor--> Intel® Core™ i5-7200U CPU @ 2.50GHz × 4
Ram--> 8GB
OS--> Fed27 workstation
(I'm not yet exposed to java.util.concurrent API 'yet' but I know I can manage threads differently there..)
I appreciate if you can explain in normal threading terms instead of referring to the Concurrent API.
Thanks for help and excuse this noob once again :)
I think if you add a little logging to your program, then it can help you to understand what is really going on:
First thing, If any thread calls a System.exit(), then the JVM terminates(killing all threads!!!). It will not wait for any thread to execute but it calls shutdown hooks, uninvoked finalizers, etc. So, it may take sometime for the JVM to finish. You can read more here:
Now, you have mentioned outputs from only 4 runs. If you run it few more times, I'm sure you will get the below output:
R2--100
This clearly means that the JVM terminated before the other thread could execute.
Now for your outputs, say
R2--100 R2--100
Both thread executed before the JVM could terminate, simple!
One thing to notice is that both thread's name is R2. This is because value variable is static and being shared between the 2 threads. Due to the race condition, before R2 can print the value, it's being set by R1. You can see this if you add the logging that I suggested.
See below sample output: