Synchronized Brief introduction of Java concurrent programming learning notes _java

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 the simplest one. The main functions of the synchronized are three: (1) To ensure that the Access synchronization code (2) is mutually exclusive, so that the modification of the shared variables can be seen in time (3) to effectively solve the reordering problem. Syntactically speaking, there are three uses of synchronized:

(1) Modification of common methods

(2) Modifying the static method

(3) Cosmetic code block

Next I will use a few examples of procedures to illustrate the three ways of using (for ease of comparison, three pieces of code in addition to the use of synchronized, the other basic consistency).

1, there is no synchronization of the situation:

Code Snippet One:

 package com.paddx.test.concurrent;
    public class Synchronizedtest {public void method1 () {System.out.println (' Method 1 start ');
      try {System.out.println ("Method 1 Execute");
    Thread.Sleep (3000);
    catch (Interruptedexception e) {e.printstacktrace ();
  } System.out.println ("Method 1 End");
    public void Method2 () {System.out.println (' Method 2 start ');
      try {System.out.println ("Method 2 Execute");
    Thread.Sleep (1000);
    catch (Interruptedexception e) {e.printstacktrace ();
  } System.out.println ("Method 2 End");

    public static void Main (string[] args) {final synchronizedtest test = new Synchronizedtest ();
      New Thread (New Runnable () {@Override public void run () {test.method1 ();

    }). Start ();
      New Thread (New Runnable () {@Override public void run () {test.method2 ();
  }). Start (); }
}

The results are as follows: Thread 1 and thread 2 Enter the execution state at the same time, thread 2 executes faster than thread 1, so thread 2 executes first, and this process threads 1 and thread 2 are executed concurrently.

Method 1 Start
Method 1 Execute
Method 2 Start
Method 2 Execute
Method 2 End
Method 1 End

2, the common method of synchronization:

Code Snippet Two:

Package com.paddx.test.concurrent;
    public class Synchronizedtest {public synchronized void Method1 () {System.out.println (' Method 1 start ');
      try {System.out.println ("Method 1 Execute");
    Thread.Sleep (3000);
    catch (Interruptedexception e) {e.printstacktrace ();
  } System.out.println ("Method 1 End");
    Public synchronized void Method2 () {System.out.println (' Method 2 start ');
      try {System.out.println ("Method 2 Execute");
    Thread.Sleep (1000);
    catch (Interruptedexception e) {e.printstacktrace ();
  } System.out.println ("Method 2 End");

    public static void Main (string[] args) {final synchronizedtest test = new Synchronizedtest ();
      New Thread (New Runnable () {@Override public void run () {test.method1 ();

    }). Start ();
      New Thread (New Runnable () {@Override public void run () {test.method2 ();
  }). Start ();

 }
}

The results are as follows, compared to the code snippet, it is clear that thread 2 needs to wait for the method1 execution of thread 1 to begin executing the METHOD2 method.

Method 1 Start
Method 1 Execute
Method 1 End
Method 2 Start
Method 2 Execute
Method 2 End

3. static method (Class) synchronization

Code Snippet Three:

Package com.paddx.test.concurrent;
     public class Synchronizedtest {public static synchronized void Method1 () {System.out.println (' Method 1 start ');
       try {System.out.println ("Method 1 Execute");
     Thread.Sleep (3000);
     catch (Interruptedexception e) {e.printstacktrace ();
   } System.out.println ("Method 1 End");
     public static synchronized void Method2 () {System.out.println (' Method 2 start ');
       try {System.out.println ("Method 2 Execute");
     Thread.Sleep (1000);
     catch (Interruptedexception e) {e.printstacktrace ();
   } System.out.println ("Method 2 End");
     public static void Main (string[] args) {final synchronizedtest test = new Synchronizedtest ();
 
     Final Synchronizedtest test2 = new Synchronizedtest ();
       New Thread (New Runnable () {@Override public void run () {test.method1 ();
 
     }). Start ();
       New Thread (New Runnable () {@Override public void Run () {test2.method2 ();
   }). Start ();

 }
 }

The results are as follows: Synchronization of static methods is essentially a synchronization of classes (static methods are essentially class-like methods, not methods on objects), so even if test and test2 belong to different objects, they all belong to instances of the Synchronizedtest class. Therefore, you can only perform method1 and method2 sequentially, and cannot execute concurrently.

Method 1 Start
Method 1 Execute
Method 1 End
Method 2 Start
Method 2 Execute
Method 2 End

4, code block synchronization

Code Snippet Four:

Package com.paddx.test.concurrent;
    public class Synchronizedtest {public void method1 () {System.out.println (' Method 1 start ');
        try {synchronized (this) {System.out.println (' Method 1 execute ');
      Thread.Sleep (3000);
    } catch (Interruptedexception e) {e.printstacktrace ();
  } System.out.println ("Method 1 End");
    public void Method2 () {System.out.println (' Method 2 start ');
        try {synchronized (this) {System.out.println (' Method 2 execute ');
      Thread.Sleep (1000);
    } catch (Interruptedexception e) {e.printstacktrace ();
  } System.out.println ("Method 2 End");

    public static void Main (string[] args) {final synchronizedtest test = new Synchronizedtest ();
      New Thread (New Runnable () {@Override public void run () {test.method1 ();

    }). Start (); New Thread (New Runnable () {@Override public void run () {TEST.METHOD2();
  }). Start ();

 }
}

The results are as follows, although thread 1 and thread 2 are all in the corresponding method to begin execution, but thread 2 needs to wait for thread 1 to complete the synchronization block before entering the synchronization block.

Method 1 Start
Method 1 Execute
Method 2 Start
Method 1 End
Method 2 Execute
Method 2 End

Second, Synchronized principle

If there are questions about the results of the above implementation, but also not urgent, we first to understand the principle of synchronized, and then look back at the question on the clear at a glance. Let's start by decompile the following code to see how synchronized implements the code block synchronization:

Package com.paddx.test.concurrent;

public class Synchronizeddemo {
  the public void method () {synchronized () {System.out.println ()} (
      "Method 1") Start ");}}


Decompile Result:

As regards the role of these two directives, we refer directly to the JVM specification in the description:

Monitorenter:

Each object is associated with a monitor. A Monitor is locked if and only if it has A 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 C Ount 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 C Ount is zero, then tries again to gain ownership.


   

The approximate meaning of this passage is:

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

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

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

3. If another thread is already using monitor, the thread goes into a blocking state until the monitor enters the number 0, and then tries to get ownership of the 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. The other threads this are blocking to enter the monitor are allowed to.

The approximate meaning of this passage is:

The thread that executes the monitorexit must be the owner of the monitor corresponding to ObjectRef.

When the instruction is executed, the monitor's entry number is reduced by 1, and if you subtract 1 and then enter the number 0, the thread exits monitor and is no longer the owner of this monitor. Other threads blocked by this monitor can try to capture the ownership of this monitor.

Through these two paragraphs, we should be able to clearly see the implementation principle of synchronized, synchronized semantic bottom is through a monitor object to complete, in fact, wait/notify and other methods also rely on the monitor object, This is why the java.lang.IllegalMonitorStateException exception can be thrown only if methods such as wait/notify are invoked in a synchronized block or method.

Let's take a second look at the decompile result of the synchronization method:

Source:

Package com.paddx.test.concurrent;

public class Synchronizedmethod {public
  synchronized void method () {
    System.out.println ("Hello world!");
  }
}

Decompile Result:

From the results of the decompile, the synchronization of the method is not done through instruction Monitorenter and monitorexit (theoretically it can be implemented by these two instructions), but the constant pool has more acc_synchronized identifiers than the normal method. The JVM implements the synchronization of the method based on the identifier: When the method is called, the calling instruction checks whether the method's acc_synchronized access flag is set, and if it is set, the execution thread acquires the monitor before it succeeds to execute the method body. After the method is finished, the monitor is released. 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 implement, do not need to pass the bytecode to complete.

Iii. explanation of Operation result

With the understanding of the principle of synchronized, then look at the above procedures can be solved.

1, Code snippet 2 results:

Although Method1 and Method2 are different methods, the two methods are synchronized and are invoked through the same object, so the call needs to compete with the lock on the same object (monitor) and only mutually exclusive access to the lock. 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, and since both method1 and method2 belong to static synchronization methods, they need to get monitor on the same class (each class only corresponds to one class object) when called. , so they can only be executed sequentially.

3, Code snippet 4 results:

Synchronization of code blocks essentially requires that you get the monitor for the object in parentheses behind the Synchronized keyword, because the contents of the parentheses in this code are all this, and method1 and METHOD2 are called by the same object. So you need to compete for the lock on the same object before entering the sync block, so you can only execute the sync block sequentially.

Four summary

Synchronized is the most common way to ensure thread safety in Java concurrent programming, and its use is relatively simple. However, if you can understand the principle of the monitor and so on, on the one hand can help us to correctly use the Synchronized keyword, on the other hand, we can help us better understand the concurrent programming mechanism, help us in different circumstances to choose a better concurrency strategy to complete the task. The various concurrent problems encountered in peacetime can also be calmly addressed.

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.