Why do you want to synchronize data with Java multithreaded programming _java

Source: Internet
Author: User

The variables in Java are divided into two categories: local variables and class variables. A local variable is a variable defined within a method, such as a variable defined in the Run method. For these variables, there is no question of sharing between threads. Therefore, they do not require data synchronization. A class variable is a variable that is defined in a class, and the scope is the entire class. This type of variable can be shared by multiple threads. Therefore, we need to synchronize the data with this type of variable.
Data synchronization means that at the same time, only one thread can access the synchronized class variable, and the current thread accesses the variables before other threads can continue to access them. The access referred to here refers to the access to write operations, and if all the threads accessing the class variables are read, they generally do not require data synchronization. What happens if you do not synchronize data with shared class variables? Let's take a look at what happens to the following code:

Copy Code code as follows:

Package test;

public class Mythread extends Thread
{
public static int n = 0;

public void Run ()
{
int m = n;
Yield ();
m++;
n = m;
}
public static void Main (string[] args) throws Exception
{
Mythread mythread = new Mythread ();
Thread threads[] = new THREAD[100];
for (int i = 0; i < threads.length; i++)
Threads[i] = new Thread (mythread);
for (int i = 0; i < threads.length; i++)
Threads[i].start ();
for (int i = 0; i < threads.length; i++)
Threads[i].join ();
System.out.println ("n =" + MYTHREAD.N);
}
}

The possible results of executing the above code are as follows:

Copy Code code as follows:

n = 59

To see this result, many readers may be surprised. This program is obviously starting up 100 threads, and then each thread will be static variable n plus 1. Finally, the Join method is used to make all 100 threads run out and then output the N value. In normal terms, the result should be n = 100. But the result is less than 100.
In fact, the culprit is the "dirty data" that we often refer to. The yield () statement in the Run method is the originator of the "dirty data" (no yield statement may produce "dirty data", but it will not be so obvious that only a 100 change to a larger number will often produce "dirty data", which in this case is called yield to magnify "dirty data." effect). The purpose of the yield method is to suspend the thread, which means that the thread that calls the yield method temporarily discards the CPU resources, giving the CPU an opportunity to execute other threads. To illustrate how this program produces "dirty data," we assume that only two threads are created: Thread1 and thread2. Because the Thread1 start method is invoked first, the Thread1 run method is generally running first. When the Thread1 run method runs to the first line (int m = n;), assigns the value of N to M. When the yield method is executed to the second line, Thread1 temporarily stops execution, and when the Thread1 is paused, Thread2 gets the CPU resources to run (before Thread2 is in a ready state), and when Thread2 executes to the first line (int m = n;) , because N is still 0 when Thread1 executes to yield, the value of M in Thread2 is also 0. As a result, Thread1 and Thread2 's M are getting 0. After they perform the yield method, they start with 0 plus 1, so no matter who executes first, the last n value is 1, except that n is assigned a value by Thread1 and Thread2. Some people may ask, if only n++, will produce "dirty data"? The answer is yes. So n++ is just a statement, and how do you give the CPU to other threads during execution? This is just a superficial phenomenon, n++ is not a language after being compiled into an intermediate language (also called a bytecode) by the Java compiler. Let's take a look at the Java intermediate language that the following Java code will be compiled into.

Copy Code code as follows:

public void Run ()
{
n++;
}

The Compiled intermediate language code
Copy Code code as follows:

public void Run ()
{
Aload_0
Dup
GetField
Iconst_1
Iadd
Putfield
Return
}

You can see that only one statement is n++ in the Run method, and there are 7 intermediate language statements after compilation. We don't need to know what the functions of these statements are, just look at lines No. 005, 007, and 008. In the 005 line is GetField, according to its English meaning know is to get a value, because there is only one n, so there is no doubt is to get the value of N. And in the 007 line of Iadd It is not difficult to guess that the resulting n value plus 1. In the 008 line of the meaning of Putfield I think you may have guessed it, it is responsible for this plus 1 after the N to update the class variable N. Speaking of this, maybe everyone still have a doubt, the implementation of n++ directly will n plus 1 not on the line, why such a fee. There is actually a problem with a Java memory model. The
Java memory model is divided into primary and working stores. The primary store holds all instances of Java. That is, after we use new to create an object, the object and its internal methods, variables, and so on are stored in this area, and the N in the Mythread class is stored in the region. The primary store can be shared by all threads. The work store is the line stacks we talked about, and in this area we keep the variables defined in the Run method and the method called by the Run method, which is the method variable. When a thread modifies a variable in the primary store, it does not modify the variables directly, but instead copies them to the current thread's working store, overwriting the corresponding variable value of the primary store after the modification is complete.
After understanding the Java memory model, it is not difficult to understand why n++ is not an atomic operation. It must pass through a copy, plus 1 and overwrite process. This process is similar to the process of simulating in the Mythread class. As you can imagine, if the thread1 was interrupted for some reason when it was executed to GetField, a similar result would occur for the Mythread class. To completely solve this problem, you must use some method to synchronize N, that is, only one thread at a time can manipulate N, also known as atomic operations on N.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.