Java multithreading (I) Race Condition phenomenon and causes
What is Race Condition?
First, what is Race Condition? Chinese Translation of Race Condition is a competitive Condition, it refers to the phenomenon that multiple processes or threads concurrently access and operate on the same data and the execution results are related to the specific sequence of access. In other words, the sequence of data access between threads or processes determines the result of data modification. This phenomenon is often seen in multithreaded programming.
Race Condition instance
Class MyThread implements Runnable {/*** calculation type, 1 indicates subtraction, others indicates addition */private int type; public MyThread (int type) {this. type = type;} public void run () {if (type = 1) for (int I = 0; I <10000; I ++) Test. num --; else for (int I = 0; I <10000; I ++) Test. num ++ ;}} public class Test {public static int num = 1000000; public static void main (String [] args) {Thread a = new Thread (new MyThread (1); Thread B = new Thread (new MyThread (2);. start (); B. start ();/** the main thread waits for the sub-thread to finish, and then prints the value */try {. join (); B. join ();} catch (Exception e) {e. printStackTrace ();} System. out. println (num );}}
The above program is very simple. It is to use two threads to operate and modify the same data at the same time. One thread wants to add num to 10000, And the other thread wants to reduce num to 10000. According to our calculation, one number is added to 10000, then subtract 10000, which is equivalent to no change, so the result should be equal to itself. But this is just our imagination. Is it true? You can run the above program and you will be surprised to find that the result is not 1000000. If you run the program several times again, the results are different each time.
Yes, this is the Race Condition. There are two threads that operate the num variable at the same time, and the operation result is related to the access sequence (this is not controlled by us, but controlled by the operating system, we can only see that each result is different ).
Reasons for Race Condition
Now we have seen the Race Condition phenomenon. How does it produce it? Don't worry about it first. Didn't you say it? It was caused by different access orders. I would like to say that learning new knowledge must be traced to the root of the source, and we must really understand why this phenomenon occurs on the hardware or operating system level?
First, let's look at a picture.
We know that in the operating system, the operating system program allocates separate registers and program counters for each thread. In the preceding figure, I divide the table into three columns. The first column indicates the operation process of thread 1, the second column indicates the operation process of thread 2, and the third column indicates the results in memory. In the figure, the small box with numbers in the first two columns indicates the registers used by the thread, and the numbers represent the values in the registers. The small box in the third column indicates a storage unit in the memory, and the value indicates the value stored in the memory.
Now let's take a look at the operation process. (This is a simplified schematic process. The real process is much more complicated.) At the beginning, data is stored in the memory. Therefore, the num is loaded into the Register through the LOAD command, then execute the corresponding operation commands, which are respectively ADD (plus 1) SUB (minus 1) commands. After the command is executed, the results are stored in the corresponding registers, the value in the memory has not changed. After the STORE command is executed, the values in the register are stored in the memory.
The ascending order of the small box indicates the process of alternating thread 1 and thread 2. First, thread 1 reads the num value in the memory, switches to thread 2 for execution, reads the num value in the memory, then executes the minus 1 operation, and finally writes the result back to the memory, at this time, the data in the memory is changed to 999999, but this change thread 1 cannot be seen, because this change occurs after thread 1 reads the num value. In fact, the data read by thread 1 is already incorrect, which is the root cause of Race Condition. Then thread 1 executes the unexecuted command, adds the 1 operation, and writes 1000001 to the memory, which is the direct cause of Race Condition, it overwrites the result of thread 2.
This is why Race Condition occurs. Do you really understand it ?.
Of course, Race Condition is not good, so we will avoid Race Condition in various ways. In the next blog, I will introduce to you how to avoid Race Condition and multi-thread synchronization and mutex in java multi-thread programming, and hope to learn and make progress together with you, please continue to follow up on my blog. If you support me, let me know.