Java Concurrency Programming: synchronized and its implementation principles

Source: Internet
Author: User

First, the basic use of synchronized

Synchronized is one of the most common methods for solving concurrency problems in Java, and is the simplest one. There are three main functions of synchronized:
(1) Ensure thread-mutually exclusive access synchronization code
(2) Ensure that changes to shared variables are visible in time
(3) Solve the reordering problem effectively. Syntactically speaking, there are three ways to use synchronized:

(a) Modification of common methods

(b) Modification of static methods

(c) Modifier code block

Next I'll illustrate the three ways to use it in a few examples (for comparison purposes, the three pieces of code are basically consistent except for the way synchronized is used).

1, there is no synchronization of the situation:

Code Snippet One:

1 Packagecom.paddx.test.concurrent;23 Public classSynchronizedtest {4 Public voidmethod1 () {5 System.out.println ("Method 1 Start");6Try {7 System.out.println ("Method 1 Execute");8 Thread.Sleep (3000);9}Catch(interruptedexception e) {10e.printstacktrace ();11 }System.out.println ("Method 1 End");13 }1415 Public voidmethod2 () {System.out.println ("Method 2 Start");17Try {System.out.println ("Method 2 Execute");Thread.Sleep (1000);20}Catch(interruptedexception e) {21ste.printstacktrace ();22 }System.out.println ("Method 2 End");24 }2526 Public Static voidMain (string[] args) {27FinalSynchronizedtest test =Newsynchronizedtest ();2829NewThread (NewRunnable () {30@Override31 Public voidrun () {32test.method1 ();33 }34}). Start ();3536NewThread (NewRunnable () {PNS @Override 38 Public voidrun () {39test.method2 ();40 }41}). Start ();42 }43}

The execution results are as follows, thread 1 and thread 2 go into execution state at the same time, thread 2 executes faster than thread 1, so thread 2 executes first, and threads 1 and thread 2 are executed concurrently.

Method 1start
Method 1execute
Method 2start
Method 2execute
Method 2end
Method 1end


2, the common method synchronization:

Code Snippet Two:

1 Packagecom.paddx.test.concurrent;23 Public classSynchronizedtest {4 Public synchronized voidmethod1 () {5 System.out.println ("Method 1 Start");6Try {7 System.out.println ("Method 1 Execute");8 Thread.Sleep (3000);3 ·Catch(interruptedexception e) {10e.printstacktrace ();11 }System.out.println ("Method 1 End");13 }1415 Public synchronized voidmethod2 () {System.out.println ("Method 2 Start");17Try {System.out.println ("Method 2 Execute");Thread.Sleep (1000);20}Catch(interruptedexception e) {21ste.printstacktrace ();22 }System.out.println ("Method 2 End");24 }2526 Public Static voidMain (string[] args) {27FinalSynchronizedtest test =Newsynchronizedtest ();2829NewThread (NewRunnable () {30@Override31 Public voidrun () {32test.method1 ();33 }34}). Start ();3536NewThread (NewRunnable () {37@Override38 Public voidrun () {39test.method2 ();40 }41}). Start ();42 }43}

The execution results are as follows, as you can clearly see from the code snippet, that thread 2 waits for thread 1 's method1 execution to finish before it starts executing the METHOD2 method.

Method 1start
Method 1execute
Method 1end
Method 2start
Method 2execute
Method 2end


3. static method (Class) synchronization

Code Snippet Three:

1 Packagecom.paddx.test.concurrent;23 Public classSynchronizedtest {4 Public Static synchronized voidmethod1 () {5 System.out.println ("Method 1 Start");6Try {7 System.out.println ("Method 1 Execute");8 Thread.Sleep (3000);3 ·Catch(interruptedexception e) {10e.printstacktrace ();11 }System.out.println ("Method 1 End");13 }1415 Public Static synchronized voidmethod2 () {System.out.println ("Method 2 Start");17Try {System.out.println ("Method 2 Execute");Thread.Sleep (1000);20}Catch(interruptedexception e) {21ste.printstacktrace ();22 }System.out.println ("Method 2 End");24 }2526 Public Static voidMain (string[] args) {27FinalSynchronizedtest test =Newsynchronizedtest ();28FinalSynchronizedtest test2 =Newsynchronizedtest ();2930NewThread (NewRunnable () {31@Override32 Public voidrun () {33test.method1 ();34 }35}). Start ();3637NewThread (NewRunnable () {38@Override39 Public voidrun () {40test2.method2 ();41 }42}). Start ();43 }44}

The result of the execution is that synchronization of static methods is essentially a synchronization of classes (static methods are essentially methods of classes, not methods on objects), so even if test and test2 belong to different objects, they all belong to instances of the Synchronizedtest class. So also can only execute method1 and method2 sequentially, cannot execute concurrently.

Method 1start
Method 1execute
Method 1end
Method 2start
Method 2execute
Method 2end


4. Code block synchronization

Code Snippet Four:

1 Packagecom.paddx.test.concurrent;23 Public classSynchronizedtest {4 Public voidmethod1 () {5 System.out.println ("Method 1 Start");6Try {7synchronized( This) {8 System.out.println ("Method 1 Execute");9 Thread.Sleep (3000);10 }11}Catch(interruptedexception e) {12e.printstacktrace ();13 }System.out.println ("Method 1 End");15 }1617 Public voidmethod2 () {System.out.println ("Method 2 Start");19Try {20synchronized( This) {System.out.println ("Method 2 Execute");Thread.Sleep (1000);23 }24}Catch(interruptedexception e) {25e.printstacktrace ();26 }System.out.println ("Method 2 End");28 }2930 Public Static voidMain (string[] args) {31FinalSynchronizedtest test =Newsynchronizedtest ();3233NewThread (NewRunnable () {34@Override35 Public voidrun () {36test.method1 ();37 }38}). Start ();3940NewThread (NewRunnable () {41@Override42 Public voidrun () {43test.method2 ();44 }45}). Start ();46 }47}

The execution results are as follows, although thread 1 and thread 2 have entered the corresponding method to begin execution, but thread 2 waits for thread 1 to complete before it enters the synchronization block.

Method 1start
Method 1execute
Method 2start
Method 1end
Method 2execute
Method 2end


Second, the principle of Synchronized

If the above implementation of the results of the question, but also do not hurry, we first to understand the principle of synchronized, and then back to the above problems at a glance. Let's start by deserializing the following code to see how synchronized implements the synchronization of code blocks:

1 package com.paddx.test.concurrent; 2 3 public class Synchronizeddemo {4 publicly void method () {5 synchronized (this) {6 System.out.println ("Method 1 Start" ); 7} 8} 9}

Anti-compilation results:

For the purpose of these two directives, we refer directly to the JVM specification:

Monitorenter:

Each object was associated with a monitor. A Monitor is locked if and only if it have an owner. The thread that executes Monitorenter attempts to gain ownership of the monitor associated with ObjectRef, as follows:
? If the entry count of the monitor associated with ObjectRef are zero, the thread enters the monitor and sets its entry Coun T to one. The thread is then the owner of the Monitor.
? If the thread already owns the monitor associated with ObjectRef, it reenters the monitor, and incrementing its entry count.
? If Another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is Zero, then tries again to gain ownership.

The approximate meaning of this passage is:

Each object has a monitor lock. When monitor is occupied, it is locked, and the thread attempts to take ownership of the monitor while executing the monitorenter instruction, as follows:

1. If the monitor has an entry number of 0, the thread enters monitor and then sets the entry number to 1, which is the owner of the Monitor.

2, if the thread already occupies the monitor, just re-enter, then enter the monitor into the number plus 1.

3. If another thread has already occupied monitor, the thread goes into a blocking state until the number of incoming monitor is 0, and then tries to get ownership of monitor again.

Monitorexit:

The thread that executes Monitorexit must is the owner of the monitor associated with the instance referenced by ObjectRef .
The thread decrements the entry count of the monitor associated with ObjectRef. If as a result the value of the entry count is zero, the thread exits the monitor and are no longer its owner. Other threads, that is blocking to enter the monitor is allowed to attempt.

The approximate meaning of this passage is:

The thread executing the monitorexit must be the owner of the monitor that corresponds to ObjectRef.

When the instruction is executed, the monitor enters the number minus 1, and if the number is 0 after minus 1, the thread exits monitor and is no longer the owner of the Monitor. Other threads that are blocked by this monitor can try to get ownership of the monitor.

Through these two paragraphs, we should be able to clearly see the implementation of the principle of synchronized, synchronized semantic bottom is through a monitor object to complete, in fact, wait/notify and other methods are also dependent on the monitor object, This is why it is only possible to call wait/notify and other methods in a synchronized block or method, or else the cause of the java.lang.IllegalMonitorStateException exception will be thrown.

Let's take a look at the results of the synchronous method's decompile:

Source:

1 package com.paddx.test.concurrent; 2 3 public class Synchronizedmethod {4 public synchronized void Method () {5 System.out.println ("Hello world!"); 6} 7}

Anti-compilation results:

From the results of the anti-compilation, the synchronization of the method is not done by the instruction Monitorenter and monitorexit (in theory it can also be achieved by the two instructions), but compared to the normal method, its constant pool has more acc_synchronized identifiers. The JVM implements the synchronization of the method according to the identifier: When the method is called, the calling instruction will check whether the acc_synchronized access flag of the method is set, and if it is set, the execution thread will get the monitor first and then the method body can be executed. The monitor is released after the method has finished executing. No other thread can get the same monitor object during the execution of the method. In fact, there is no difference, but the method of synchronization is an implicit way to achieve, without the bytecode to complete.

Iii. Explanation of running results

With the understanding of the principle of synchronized, and then see the above procedure can be solved.

1. Code Snippet 2 Results:

Although Method1 and Method2 are different methods, both of these methods are synchronized and are called by the same object, so the call must first compete with the lock on the same object (monitor), and it can only get the lock mutually exclusive, so Method1 and METHOD2 can only be executed sequentially.

2. Code Snippet 3 Results:

Although Test and test2 belong to different objects, test and test2 belong to different instances of the same class, because both Method1 and method2 are static synchronous methods, so calls need to get the same class monitor (only one class object for each) , so it can only be executed sequentially.

3. Code Snippet 4 Results:

For code block synchronization, you essentially need to get the monitor of the object in parentheses after the Synchronized keyword, because the contents of the parentheses in this code are this, and method1 and METHOD2 are called by the same object. So you need to compete for locks on the same object before entering the synchronization block, so you can only execute the synchronization blocks sequentially.

Iv. Summary

Synchronized is the most common way to ensure thread safety in Java concurrent programming, and its use is relatively simple. But if we can understand the principle of the monitor lock and other basic knowledge, on the one hand can help us to correctly use the Synchronized keyword, on the other hand can also help us to better understand the concurrency programming mechanism, helps us to choose a better concurrency strategy in different situations to complete the task. For the usual problems encountered in the concurrency, but also can calmly deal with.

Java Concurrency Programming: synchronized and its implementation principles

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.