Global sum error of multithreading in Java
I'm new to multithreading in Java. I made some code to see how it works I use global = 0 as the global int variable and use the for loop to initialize a large number of threads (100) to add 1 to my global variable At the end of the code, the result should be 100, but not I sometimes end the code with 99 or any other number (about 100) So my question is, why do threads "fight" between them and can't make the sum correct?
public class test extends Thread { public static int global =0; public static void main(String[] args) throws Exception { for(int i=0;i<100;i++){ String stream = String.valueOf(i); new test2(stream).start(); } Thread.sleep(1000); System.out.println(global); } public test(String str) { super(str); } public void run() { int a = Integer.parseInt(getName()); global = global+1; System.out.println("El hilo "+a+" tiene el número "+global); } }
I know I don't need int a = integer parseInt(getName());, But I pretend you'll use that name in the future And if I delete it now, the result is wrong
Solution
This is a classic competition condition
One of your threads, called "a", has read the global value, such as 10, and added 1 to it, but it does not store the value 11 back to the global
Your other thread, called "B", is now reading the global "old" value, 10, it is adding 1 to it, and it stores the value 11 back to the global
Thread "a" is then eventually allowed to store its value 11 back to the global Two increments have occurred, but the end result is that only one increment has occurred effectively
This happens because the operation of incrementing and storing it back to a variable is not atomic This means that there are multiple separate operations that may produce incorrect results if interrupted
You must create a synchronized block to enforce atomic operations You can lock the class object itself
synchronized (test.class) { global = global+1; }
As an alternative, you can set the global variable to atomicinteger, which handles atomic updates for you