Java Multi-threaded Note II (Synchronized and implementation principles) __java

Source: Internet
Author: User
Sync keyword synchronized

Java keyword synchronized is used to mark methods or blocks of code are synchronized. It is one of the most common methods in Java to solve concurrency problems: (1) Ensure that the Access synchronization code (2) that is mutually exclusive to the thread ensures that the modification of the shared variables can be seen in time.
There are four ways to use synchronized:
(1) Modification of common methods
(2) Modifying the static method
(3) Modify the code block in the normal method
(4) Modifying the code block in the static method to modify the common method

public class Synchronizedtest {//Method 1, perform 3 sec public synchronized void Method1 () {System.out.println ()
        1 start ");
            try {System.out.println ("method1 execute");
        Thread.Sleep (3000);
        catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace ();
    } System.out.println ("Method1 end");
        }//Method 2, execute 1 SEC public synchronized void Method2 () {System.out.println ("method2 start");
            try {System.out.println ("method2 execute");
        Thread.Sleep (1000);
        catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace ();
    } System.out.println ("Method2 end");
        public static void Main (string[] args) {final synchronizedtest test = new Synchronizedtest (); Thread 1 new Thread (new Runnable () {@Override public void run () {test.method1 ();
        }). Start (); Thread 2 new Thread (new Runnable () {@Override public void run () {Test.metho
            D2 ();
    }). Start (); }
}

Output:

Method1 start
method1 execute
method1 end
method2 start
method2 execute
method2 end

The Synchronized keyword tells Java that the method is synchronized. synchronization, which is synchronized on the object that owns the method. For an instance, only one thread can run in this method synchronization block. If more than one instance exists, each instance corresponds to a thread.
In this case, thread 2 needs to wait for the method1 execution of thread 1 to begin executing the METHOD2 method. Because for the test instance, only one thread at a time can run its synchronization method.

If you remove the Synchronized keyword from this example, the output is:

Method1 start
method1 execute
method2 start
method2 execute
method2 end
Method1 End

Because thread 1 and thread 2 are in the execution state at the same time, Method 2 executes faster than Method 1, so Method 2 executes first, and this process threads 1 and thread 2 are executed concurrently. Modifying static methods

public class Synchronizedtest {//Method 1, perform 3 seconds public static synchronized void Method1 () {System.out.println (
        "Method1 start");
            try {System.out.println ("method1 execute");
        Thread.Sleep (3000);
        catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace ();
    } System.out.println ("Method1 end");
        }//Method 2, perform 1-second public static synchronized void Method2 () {System.out.println ("method2 start");
            try {System.out.println ("method2 execute");
        Thread.Sleep (1000);
        catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace ();
    } System.out.println ("Method2 end");
        public static void Main (string[] args) {final synchronizedtest test1 = new Synchronizedtest ();
        Final Synchronizedtest test2 = new Synchronizedtest (); Thread 1 NEW Thread (New Runnable () {@Override public void run () {test1.method1 ();
        }). Start (); Thread 2 new Thread (new Runnable () {@Override public void run () {Test2.meth
            OD2 ();
    }). Start (); }
}

Output:

Method1 start
method1 execute
method1 end
method2 start
method2 execute
method2 end

Synchronization of a static method is essentially a synchronization of a class (static methods are inherently a method of a class, not a method on an object), so even though test1 and test2 belong to different objects, they all belong to instances of the Synchronizedtest class, so you can only execute threads sequentially, cannot be executed concurrently. to modify a block of code in a normal method

Sometimes you don't need to sync the whole method, but it's part of the synchronization method.

public class Synchronizedtest {//Method 1, execute 3 sec public void Method1 () {System.out.println ("method1 start");
                try {synchronized (this) {System.out.println ("method1 execute");
            Thread.Sleep (3000); The catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace (
        );
    } System.out.println ("Method1 end");
        }//Method 2, execute 1 sec public void Method2 () {System.out.println ("method2 start");
                try {synchronized (this) {System.out.println ("method2 execute");
            Thread.Sleep (1000); The catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace (
        );
    } System.out.println ("Method2 end");
        public static void Main (string[] args) {final synchronizedtest test = new Synchronizedtest ();
     Thread 1   New Thread (New Runnable () {@Override public void run () {test.method1 ();
        }). Start (); Thread 2 new Thread (new Runnable () {@Override public void run () {Test.metho
            D2 ();
    }). Start (); }
}

Output:

Method1 start
method1 execute
method2 start
method1 end
method2 execute
method2 end

Although thread 1 and thread 2 are all in the appropriate way to begin execution, thread 2 waits until the synchronization block in thread 1 completes before entering the synchronization block.

Objects enclosed in parentheses in the synchronization builder are called Monitor objects . In the example above, this is used, which is the instance itself that invokes the method. The code above uses a monitor object to synchronize and uses an instance of the calling method itself as the monitor object . Only one thread at a time can run the synchronization block code of the same monitor object . modifying code blocks in a static method

This is very similar to the code block in the cosmetic normal method, which simply changes the monitor object to a class object . The above side of the procedure for example, the synchronized (this) to synchronized (Synchronizedtest.class) can be. Synchronized Principle Reverse compilation of synchronization block program

Let's start by decompile The following code to see how synchronized implements synchronization blocks :

Package com.paddx.test.concurrent;
public class Synchronizeddemo {public
    void method () {
        synchronized () {
            System.out.println () 1 start ");}}}

Decompile Result:

What is the function of these two directives (Monitorenter and Monitorexit) in the red box. First look at the Monitorenter:

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 the number of monitor entry is 0, the thread enters monitor and then sets the entry number to 1, which is the owner of Monitor.
(2) If the thread already owns the monitor and just re-enter it, enter the number of monitor entry 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.

Look again Monitorexit:

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 the above two paragraphs, we can see in the synchronized code block synchronized implementation principle, 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 is thrown if methods such as wait/notify can be invoked only in a synchronized block or method. reverse compilation of synchronization methods:


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. The JVM is based on the identifier to achieve the synchronization of the method, specific:
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, and then releases the monitor after the method is finished. 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. Review

With the understanding of the principle of synchronized, then look at the above procedures can be solved.
(1) Examples in the section "Modifying the Common method":
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) Examples in the section "Modifying a static method":
Although Test1 and test2 belong to different objects, test1 and test2 belong to different instances of the same class, and since both method1 and method2 belong to static synchronization methods, So the call needs to get monitor on the same class (each class corresponds to only one class object), so it can only be executed sequentially.

(3) Examples of the section "Modifying code blocks in common methods":
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.


The original source: Concurrent Programming Network-java synchronization block
Liuxiaopeng-java concurrent programming: synchronized and its implementation principle

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.