Java multithreading summary started with synchronized

Source: Internet
Author: User

The most important one is:
Synchronized is used for implicit locks of objects. Note that it is an object!

For example, this example does not have any business meaning, just to illustrate the basic usage of synchronized:
Java code
Class MyClass (){
Synchronized void myFunction (){
// Do something
}
}

Public static void main (){
MyClass myClass = new MyClass ();
MyClass. myFunction ();
}

Okay, that's easy.
The myFunction () method is a synchronous method. Who is the implicit lock? A: It is the object of the class where the method is located.
See how to use: myClass. myFunction (); it is clear that the implicit lock is myClass.
To understand this, the thread wants to execute myClass. myFunction (); it must first obtain the Lock of myClass.

The following is a summary:
1. the synchronized keyword has two scopes:
1) In an object instance, synchronized aMethod () {} can prevent multiple threads from simultaneously accessing the synchronized Method of the object (if an object has multiple synchronized methods, as long as a thread accesses one of the synchronized methods, other threads cannot simultaneously access any of this object's synchronized methods ). At this time, the synchronized methods of different object instances are irrelevant. That is to say, other threads can access the synchronized Method in another object instance of the same class at the same time;

2) is the scope of a class. synchronized static aStaticMethod {} prevents multiple threads from simultaneously accessing the synchronized static method in this class. It can work on all object instances of the class. (Note: This can be considered to work for Class objects)

2. In addition to using the synchronized keyword before the method, the synchronized keyword can also be used in a block in the method, indicating that only the resources in this block are mutually exclusive. Usage: synchronized (this) {/* block */}. Its scope is this, which is the current object. Of course, this bracket can be any object. The meanings and usage of the synchronized Method and block are not essentially different;

3. the synchronized keyword cannot be inherited. That is to say, the method of the base class synchronized f () {} is not automatically synchronized f () {} in the inheritance class (){}, instead, it becomes f (){}. You need to explicitly specify a method of the inherited class as the synchronized method;

Synchronized may cause deadlocks, for example:
Java code
Class DeadLockSample {
Public final Object lock1 = new Object ();
Public final Object lock2 = new Object ();

Public void methodOne (){
Synchronized (lock1 ){
...
Synchronized (lock2 ){...}
}
}

Public void methodTwo (){
Synchronized (lock2 ){
...
Synchronized (lock1 ){...}
}
}
}

Suppose that scenario: thread A calls methodOne () and obtains the implicit lock of lock1. After obtaining the implicit lock of lock2, thread B enters the operation and calls methodTwo (), the lock2 implicit lock is obtained first. At this time, thread A waits for thread B to hand over lock2, thread B waits for lock1 to enter the method block, and the deadlock is created.

The following example shows how to use synchronized, wait (), and policyall.
Here we will first introduce these two methods:
Wait ()/notify (): calls the wait () method of any object to cause thread blocking and the lock on this object is released. However, calling the notify () method of any object causes the wait () method of the object to be called () method ).

Now let's take a look at the relationship between synchronized and the two methods:
1. Where synchronized exists, wait and notify may not be available.

2. with wait, synchronized must be used in zooy. this is because wait and policy do not belong to the Thread class, but to the methods that every Object has (in fact, these two methods are in the Object class). Moreover, these two methods are related to the Object lock, synchronized is required when there is a lock.
Slow down. Let's think about whether the Java design is reasonable? As mentioned above, the lock is for the object. The wait ()/notify () operation is related to the object lock, so the wait ()/notify () the design is also reasonable in the Object.
Well, let's try again. Why is synchronized available in wait and notify?
The current thread occupies the lock in the synchronized method. On the other hand, the lock on the object that calls the wait () notify () method must be owned by the current thread. Therefore, the wait () notify () method call must be placed in the synchronized method. The Lock Object of the synchronized method is the object that calls the wait () notify () method. If this condition is not met, the program can still be compiled, but the IllegalMonitorStateException will occur at runtime.

Well, the above preparation knowledge is sufficient. Now, for example: bank transfers, only one person can transfer money at the same time.
We naturally think of a synchronous transfer method in the Bank class:
Java code
Public Class Bank (){
Float account [ACCOUNT_NUM];
...
Public synchronized void transfer (from, to, amount ){
// Transfer
}
}

Now there is a question: What should I do if a person acquires a bank lock but has insufficient balance?
Well, let's make improvements:
Java code
Public Class Bank (){
Float account [ACCOUNT_NUM];
...
Public synchronized void transfer (int from, int to, float amount ){
While (account [from]) {
Wait ();
}
Account [from]-= amount;
Account [to] + = amount;
Policyall ();
}
}

In this way, the requirements are met.
It can be seen that the object lock is used to manage the thread attempting to enter the synchronized method,
In addition, it is determined by conditions to manage the thread that has entered the synchronization method, that is, the current thread.
Here, two additional points are added:
1. It is best to use the while clause before calling the wait () method, instead of the if clause; because the while clause can be used to determine the conditions again after being awakened, and the if clause can only be judged once.
2. policyall () takes precedence over policy ().
Note the following:
Only the current thread can call wait ()/notify (), provided that the object lock must be obtained, that is, it must enter the synchronized method.

------------------------------------- I am a split line ----------------------------------------

Adding a little knowledge about JMM is good for understanding thread synchronization.
(Note: The following content refers to some fragmented posts on the Internet. It is not a copy and has no commercial purpose. Do not cross-province .)

In JVM (Note: The two storage zones mentioned at the moment are only unrelated to the physical storage zone in jvm), there is a Main Memory (Main Memory), and all the variables in Java are stored in the Main Memory, all instance and instance fields are in this region, and all threads are shared (equivalent to the blackboard, which can be seen by others ). Each thread has its own Working Memory (Working Memory), which stores copies of variables in the main Memory (equivalent to its own notebook, which can only be seen by itself ), the working memory is composed of the cache and the stack. The cache stores the copy of the variables in the primary storage, and the stack stores the local variables in the thread. The thread operates on all variables in the working memory, and the threads cannot directly access the working memory. The passing of variable variables worth changing must be completed by the main memory. The variable value modified by the concurrent thread in JMM must be synchronized to the main memory through the thread variable before other threads can access it.
Check whether the image is more vivid.
 

Well, let's take a look at the thread's operation steps for a variable:
1. Copy data from the master memory to the working memory
2. Execute Code to perform various operations and calculations on data.
3. Write the variable value after the operation back to the main memory.

Now, for example, we assume that two players are playing games on two terminal monitors (Working Memory), while the audience is watching their games on the server screen (Main Memory. The two players are equivalent to threads in synchronization, and the audience is equivalent to other threads. A player cannot directly operate on the server's large screen. He can only view his terminal display. He can only copy the current result to his terminal from the server first (step 1 ), then, operate on your terminal (step 2), record the operation result on the terminal, and synchronize it to the server at a certain time (Step 3 ). The result he can see is to copy the content from the server to his terminal, and to make the result of his operations visible to others, it must be synchronized to the server. When to synchronize, it depends on the communication mechanism between the terminal and the server.

Back to these three steps, this order is what we want, but JVM does not guarantee that steps 1st and 3rd will be executed immediately in the above Order. According to the java language specification, the data exchange between the thread's working memory and the main memory is loosely coupled. When should I refresh the working memory or when should I update the content of the main memory, it can be determined by the specific Virtual Machine implementation. Because JVM can optimize the feature code, it changes the order of some running steps, therefore, it is not guaranteed whether the value in the working memory is directly obtained when the thread calls the variable or the value is copied from the primary memory first, which may happen in any case. Similarly, after a thread changes the value of a variable, it is not guaranteed whether to immediately write the variable back to the primary storage. Maybe it will be immediately written, maybe it will be written again later. In the multi-threaded application scenario, a problem occurs. Multiple Threads access the same code block at the same time. It is very likely that a thread has changed the value of a variable, of course, the change is only limited to changes in the working memory. At this time, the JVM cannot ensure that the changed value is immediately written to the main memory, this means that other threads may not immediately get the changed value, and still perform various operations and operations on the old variables, resulting in unexpected results.

How can this be done? Fortunately, synchronized and volatile:
1. fields common to multiple threads should be protected by synchronized or volatile.
2. synchronized is responsible for the mutual exclusion between threads. At the same time, only one thread can execute the code in synchronized.
Synchronized has another role: Before the thread enters the synchronized block, it will map all the content in the working memory to the main memory, then, clear the working memory and copy the latest value from the primary memory. When the thread exits the synchronized block, the value in the working memory will also be mapped to the main memory, but the working memory will not be cleared at this time. In this way, it can be forced to run in the above order, to ensure that after the thread executes the code block, the value in the working memory is consistent with the value in the main memory, to ensure data consistency!
3. volatile is responsible for synchronizing the variables in the thread and the primary storage area, but not for synchronizing the variables between each thread.
Volatile means that when a thread tries to read a volatile variable, it will read the latest value from the main memory area. It is clear now.

------------------------------------- I am also a split line ----------------------------------------

Speaking of synchronized, let's talk about ThreadLocal.
In the jdk api document, the first sentence of ThreadLocal definition is: This class provides thread-local variables. Good, This class provides local variables of the thread. Let's take a look at this sentence. Let's take a look at the above knowledge of JMM:
We already know that synchronized means synchronization, that is, it targets the variables in the primary storage, in multi-thread execution, each thread needs to complete the three steps (that is, the three steps for interaction between the main memory and the working memory of the thread) to implement synchronization ), we naturally think:
1. Purpose: some variables must be shared among multiple threads to be synchronized.
2. execution efficiency: intuitively, the synchronization execution efficiency is definitely not high. In fact, it does. Why? Let's take a look at the three steps.
Okay. Now let's take a look at the definition of ThreadLocal. What can we think?
First of all, let's think about a problem. Not all multi-threaded programs need to be shared. Isn't there much need to be synchronized? It is okay for each thread to maintain its own variables, but it does not need to be shared. Yes, ThreadLocal does this. On the other hand, it is worth noting that the performance is definitely superior.
Conclusion: To compare synchronized and ThreadLocal, you must first understand whether variables need to be shared if they are used for different purposes. That is to say, ThreadLocal is not synchronous at all. Let's talk a little more: ThreadLocal and Synchonized are both used to solve multi-thread concurrent access. However, ThreadLocal is essentially different from synchronized. synchronized uses a lock mechanism to allow a variable or code block to be accessed by only one thread at a time. ThreadLocal provides a copy of the variable for each thread, so that each thread does not access the same object at a certain time, thus isolating multiple threads from sharing data. Synchronized is used for data sharing between threads, while ThreadLocal is used for data isolation between threads. The two are in different problem domains. If this is not clear, it is useless to say more, but it will be even more confused.

Okay. The previous example shows how to use ThreadLocal.

Java code
Public class TreadLocalDemo implements Runnable {
Private final static ThreadLocal studentLocal = new ThreadLocal (); // ThreadLocal

Public static void main (String [] agrs ){
TreadLocalDemo td = new TreadLocalDemo ();
Thread t1 = new Thread (td, "");
Thread t2 = new Thread (td, "B ");
T1.start ();
T2.start ();
}

Public void run (){
AccessStudent ();
}

Public void accessStudent (){
String currentThreadName = Thread. currentThread (). getName ();
System. out. println (currentThreadName + "is running! ");
Random random = new Random ();
Int age = random. nextInt (100 );
System. out. println ("thread" + currentThreadName + "set age to:" + age );
Student student = getStudent (); // each thread maintains a Student variable independently.
Student. setAge (age );
System. out. println ("thread" + currentThreadName + "first read age is:" + student. getAge ());
Try {
Thread. sleep (5000 );
}
Catch (InterruptedException ex ){
Ex. printStackTrace ();
}
System. out. println ("thread" + currentThreadName + "second read age is:" + student. getAge ());

}

Protected Student getStudent (){
Student student = (Student) studentLocal. get (); // get from ThreadLocal object
If (student = null ){
Student = new Student ();
StudentLocal. set (student); // create
}
Return student;
}

Protected void setStudent (Student student ){
StudentLocal. set (student); // put it in the ThreadLocal object
}
}

ThreadLocal uses a Map to hold a copy of variables for each thread. ThreadLocal objects are used to maintain these independent variables in key-value pairs.

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.