Difference between Synchronized and Static Synchronized

Keywords: Java IE jvm REST

By analyzing these two usages, we can understand the concept of lock in java. One is instance lock (lock on an instance object, if the class is a single instance, then the lock also has the concept of global lock). The other is global lock (the lock is for a class, no matter how many objects are instance, then the thread shares the lock). The instance lock corresponds to the synchronized keyword, while the class lock (global lock) corresponds to the static synchronized (or locked on the class or classloader object of the class). The following article makes a good summary:

 

1. Difference between synchronized and static synchronized

Synchronized is to lock the current instance of the class to prevent other threads from accessing all synchronized blocks of the instance of the class at the same time. Note that this is "current instance of the class". There is no such constraint for two different instances of the class. Then static synchronized is just to control the access of all instances of the class. Static synchronized is to restrict threads to access all instances of the class in the jvm at the same time and access the corresponding code quickly. In fact, if there is synchronized in a method or a code block in a class, then after generating an instance of the class, the modified class will have a fast monitoring speed, and the thread will be placed concurrently to access the modified instance. Synchronized protection is fast, while static synchronized is a fast monitoring speed shared by all instances of the class, which is the difference between the two, That is to say, synchronized is equivalent to this.synchronized, while static synchronized is equivalent to Something.synchronized

A Japanese author, jiechenghao's java multithreading design pattern, has such a column:

pulbic class Something(){
    public synchronized void isSyncA(){}
    public synchronized void isSyncB(){}
    public static synchronized void cSyncA(){}
    public static synchronized void cSyncB(){}
}

So, if there are two instances x and y of Something class, which of the following groups of methods can be accessed by more than one thread at the same time

a. x.isSyncA()And x.isSyncB() 
b. x.isSyncA()And y.isSyncA()
c. x.cSyncA()And y.cSyncB()
d. x.isSyncA()And Something.cSyncA()

Here, it is clear to judge:

In case a, it is the synchronized domain access to the same instance, so it cannot be accessed at the same time
 Case b is specific to different instances, so it can be accessed at the same time
 In case c, because it is static synchronized, there will still be restrictions between different instances, equivalent to Something.isSyncA() and Something.isSyncB(), so they cannot be accessed at the same time.
In case d, the answer in the book can be accessed at the same time. The reason for the answer is that syncronzied is due to the difference between the instance method and the syncronzied class method due to lock.

Personal analysis means that synchronized and static synchronized are equivalent to two gangs, each of which is in charge of its own. There is no restriction between them and they can be accessed at the same time. At present, it is not clear how to implement synchronzied in java.
Example:

public class TestSynchronized   
{    
    public synchronized void test1()   
    {    
              int i = 5;    
              while( i-- > 0)   
              {    
                   System.out.println(Thread.currentThread().getName() + " : " + i);    
                   try   
                   {    
                        Thread.sleep(500);    
                   }   
                   catch (InterruptedException ie)   
                   {    
                   }    
              }    
    }    
      
    public static synchronized void test2()   
    {    
         int i = 5;    
         while( i-- > 0)   
         {    
              System.out.println(Thread.currentThread().getName() + " : " + i);    
              try   
              {    
                   Thread.sleep(500);    
              }   
              catch (InterruptedException ie)   
              {    
              }    
         }    
    }    
      
    public static void main(String[] args)   
    {    
         final TestSynchronized myt2 = new TestSynchronized();    
         Thread test1 = new Thread(  new Runnable() {  public void run() {  myt2.test1();  }  }, "test1"  );    
         Thread test2 = new Thread(  new Runnable() {  public void run() { TestSynchronized.test2();   }  }, "test2"  );    
         test1.start();    
         test2.start();    
//         TestRunnable tr=new TestRunnable();  
//         Thread test3=new Thread(tr);  
//         test3.start();  
    }   
    
}  

Operation result:

test1 : 4  
test2 : 4  
test1 : 3  
test2 : 3  
test2 : 2  
test1 : 2  
test2 : 1  
test1 : 1  
test1 : 0  
test2 : 0  

The above code synchronized modifies both the static method and the instance method, but the running results are alternating, which proves that the class lock and the object lock are two different locks, controlling different areas, and they do not interfere with each other. Similarly, when a thread obtains an object lock, it can also obtain such a lock, that is, two locks at the same time, which is allowed.

Conclusion: A: synchronized static is the scope of a class. synchronized static cSync {} prevents multiple threads from accessing synchronized static methods in this class at the same time. It works on all object instances of a class.

B: synchronized is the scope of an instance. synchronized isSync() {} prevents multiple threads from accessing the synchronized method in the instance at the same time.

In fact, the summary is very simple.

A lock is a class object, and a lock is an instance object.
If the class object is locked, all synchronization methods of the class object are locked;
If the instance object is locked, all synchronization methods of the instance object are locked.

2. The difference between synchronized method and synchronized code

There is no difference between synchronized methods() {} and synchronized (this) {}, but synchronized methods() {} is easy to read and understand, while synchronized (this) {} can control the conflict restricted access area more precisely, sometimes showing a more efficient rate.

3. The synchronized keyword cannot be inherited

As we can see in the article http://www.learndiary.com/archives/diaries/2910.htm, I think it is also worth noting that the override method of subclass must be displayed and defined as synchronized when inheriting. (however, if the inherited development environment is used, the synchronized keyword will be added by default.)

Efficiency comparison of two ways:

1. Synchronization block, the code is as follows:

package com.bjtest.belen;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class TestSynchronized {
 
        /**
         * @param args
         */
        public static void main(String[] args) {
            
            ExecutorService service = Executors.newCachedThreadPool();
            final CountDownLatch cdOrder = new CountDownLatch(1);
            final CountDownLatch cdAnswer = new CountDownLatch(3);
            
            final SynchonizedClass sc = new SynchonizedClass();
            for(int i=0; i<3; i++){
                Runnable runnable = new Runnable(){
 
                    public void run() {
                        try{
                            cdOrder.await();
                            sc.start();
                            cdAnswer.countDown();
                        }catch(Exception e){
                            e.printStackTrace();
                        }
                    }
                    
                };
                service.execute(runnable);
            }
            try{
                Thread.sleep((long) (Math.random()*10000));
                System.out.println("thread" + Thread.currentThread().getName() + 
                        "Issue execution command");
                cdOrder.countDown();
                long beginTime = System.currentTimeMillis();
                System.out.println("thread" + Thread.currentThread().getName() + 
                "Command sent, waiting for results");
                cdAnswer.await();
                System.out.println("thread" + Thread.currentThread().getName() + 
                "All response results received,The time used is:" + (System.currentTimeMillis()-beginTime));
            }catch(Exception e){
                e.printStackTrace();
            }
            service.shutdown();
    }
}
 
class SynchonizedClass{
    
    public void start() throws InterruptedException{
        
        Thread.sleep(100);//Execution of other logic takes time
        synchronized(this){
         System.out.println("I run with 10 ms");
        }
    }
}

The operation results are as follows:

Thread main issues execution command
 Thread main has sent command, waiting for result
 I ran for 10 ms
 I ran for 10 ms
 I ran for 10 ms
 Thread main has received all the response results, time: 110

 

Synchronization method, the code is as follows:

package com.bjtest.belen;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class TestSynchronized {
 
        /**
         * @param args
         */
        public static void main(String[] args) {
            
            ExecutorService service = Executors.newCachedThreadPool();
            final CountDownLatch cdOrder = new CountDownLatch(1);
            final CountDownLatch cdAnswer = new CountDownLatch(3);
            
            final SynchonizedClass sc = new SynchonizedClass();
            for(int i=0; i<3; i++){
                Runnable runnable = new Runnable(){
 
                    public void run() {
                        try{
                            cdOrder.await();
                            sc.start();
                            cdAnswer.countDown();
                        }catch(Exception e){
                            e.printStackTrace();
                        }
                    }
                    
                };
                service.execute(runnable);
            }
            try{
                Thread.sleep((long) (Math.random()*10000));
                System.out.println("thread" + Thread.currentThread().getName() + 
                        "Issue execution command");
                cdOrder.countDown();
                long beginTime = System.currentTimeMillis();
                System.out.println("thread" + Thread.currentThread().getName() + 
                "Command sent, waiting for results");
                cdAnswer.await();
                System.out.println("thread" + Thread.currentThread().getName() + 
                "All response results received,The time used is:" + (System.currentTimeMillis()-beginTime));
            }catch(Exception e){
                e.printStackTrace();
            }
            service.shutdown();
    }
}
 
class SynchonizedClass{
    
    public synchronized void start() throws InterruptedException{
        
        Thread.sleep(100);//Execution of other logic takes time
//      synchronized(this){
         System.out.println("I run with 10 ms");
//      }
    }
}

The operation results are as follows:

Thread main issues execution command
 Thread main has sent command, waiting for result
 I ran for 10 ms
 I ran for 10 ms
 I ran for 10 ms
 Thread main has received all the response results, time: 332

Difference between the two: 222ms.

Next, we will focus on the use of synchronized in java, specifically: synchronization method and synchronization block

The synchronized keyword, which includes two uses: the synchronized method and the synchronized block.

1. synchronized method: declare the synchronized method by adding the synchronized keyword in the method declaration. Such as:

 

public synchronized void accessVal(int newVal);

The synchronized method controls access to class member variables: each class instance corresponds to a lock, and each synchronized Method must obtain the lock of the class instance calling the method before it can be executed. Otherwise, the thread to which the method belongs is blocked. Once the method is executed, the lock will be exclusive until it returns from the method. After that, the blocked thread can obtain the lock and enter the executable state again. This mechanism ensures that for each class instance at the same time, at most one of its member functions declared as synchronized is in an executable state (because at most one can obtain the lock corresponding to the class instance), thus effectively avoiding the access conflict of class member variables (as long as all methods that may access class member variables are declared as synchronized).

In Java, not only class instances, but also each class corresponds to a lock. In this way, we can also declare the static member function of the class as static synchronized to control its access to the static member variable of the class.

The defect of synchronized method: if a large method is declared as synchronized, it will greatly affect the efficiency. Typically, if a thread class's method run() is declared as synchronized, because it has been running for the whole life of the thread, its call to any synchronized method of this class will never succeed. Of course, we can put the code of the class member variable in a specific way, declare it as synchronized, and use it to solve this problem in the main method, but Java provides us with a better solution, that is, synchronized block.

2. synchronized block: the synchronized block is declared by the synchronized keyword. The syntax is as follows:

  

synchronized(syncObject) {

  //Code to allow access control

  }

synchronized block is a code block in which the code must obtain the lock of the object syncObject (as mentioned above, it can be a class instance or a class) before execution. The specific mechanism is the same as mentioned above. Because it can be targeted at any code block, and can specify any locked object, it has high flexibility.

Be careful:
When using the synchronized keyword, you should avoid using sleep or yield method in the synchronized method or synchronized block as much as possible, because the synchronized block holds the object lock, and other threads can only execute after you wake up when you rest. Not only does it seriously affect efficiency, it's also illogical.
Similarly, it doesn't make sense to call the yeld method in the synchronization block to give up CPU resources, because you occupy the lock, and other exclusive threads still can't access the synchronization block. Of course, threads that have nothing to do with synchronizing blocks can get more execution time.

Conclusion:

Basic test class:

package com.quant.dev.modules.dev.enetity;
    /**
     * @program: dev
     * @description:
     * @author: Mr.EternityZhang
     * @create: 2019-06-24 17:07
     */
    public class TestSync {
        //Code block
        public void test1()
        {
            synchronized(this)
            {
                int i = 5;
                while( i-- > 0)
                {
                    System.out.println(Thread.currentThread().getName() + " : " + i);
                    try
                    {
                        Thread.sleep(500);
                    }
                    catch (InterruptedException ie)
                    {
                    }
                }
            }
        }
        //Synchronization method
        public synchronized void test2()
        {
            int i = 5;
            while( i-- > 0)
            {
                System.out.println(Thread.currentThread().getName() + " : " + i);
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException ie)
                {
                }
            }
        }
        //Synchronization method
        public  synchronized void test3()
        {
            int i = 5;
            while( i-- > 0)
            {
                System.out.println(Thread.currentThread().getName() + " : " + i);
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException ie)
                {
                }
            }
        }
        //Synchronous static method
        public static synchronized void test4()
        {
            int i = 5;
            while( i-- > 0)
            {
                System.out.println(Thread.currentThread().getName() + " : " + i);
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException ie)
                {
                }
            }
        }
        //Common method
        public void test5()
        {
            int i = 5;
            while( i-- > 0)
            {
                System.out.println(Thread.currentThread().getName() + " : " + i);
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException ie)
                {
                }
            }
        }
    
    }

1. The synchronized keyword has two scopes:


    1)Within an object instance, synchronized aMethod(){}It can prevent multiple threads from accessing the object at the same time synchronized Method (if an object has more than one synchronized Method, as long as one thread accesses one of them synchronized Method, other threads cannot access any of this object at the same time synchronized Method). In this case, the synchronized The method is non-interference. That is to say, other threads can also access the synchronized Method;
    
    public static void main(String[] args)
        {
            final TestSync myt1 = new TestSync();
            Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test2();  }  }, "test1"  );
            Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test3();   }  }, "test2"  );
            test1.start();
            test2.start();
    
        }
    //Execution result:
    test1 : 4
    test1 : 3
    test1 : 2
    test1 : 1
    test1 : 0
    test2 : 4
    test2 : 3
    test2 : 2
    test2 : 1
    test2 : 0
    //Verification: if the same object is acquired by one thread, another thread cannot access other synchronized methods until the lock is released
    
    //Change the main method:
    public static void main(String[] args)
    {
        final TestSync myt1 = new TestSync();
        final TestSync myt2 = new TestSync();
        Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test2();  }  }, "test1"  );
        Thread test2 = new Thread(  new Runnable() {  public void run() { myt2.test3();   }  }, "test2"  );
        test1.start();
        test2.start();

    }
    //Execution result:
    test2 : 4
    test1 : 4
    test1 : 3
    test2 : 3
    test2 : 2
    test1 : 2
    test2 : 1
    test1 : 1
    test2 : 0
    test1 : 0
    //Verification: other threads can also access the synchronized method in another object instance of the same class at the same time; at the same time, it is proved that synchronized is an unfair lock, and the first thread does not have to execute first
    

    2)Is the scope of a class, synchronized static aStaticMethod{}Prevent different instance objects (or the same instance object) in multiple threads from accessing the synchronized static Method. It works on all object instances of a class.
    public static void main(String[] args)
    {
        final TestSync myt1 = new TestSync();
        final TestSync myt2 = new TestSync();
        Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test4();  }  }, "test1"  );
        Thread test2 = new Thread(  new Runnable() {  public void run() { myt2.test4();   }  }, "test2"  );
        test1.start();
        test2.start();

    }
    //Execution result:
    test1 : 4
    test1 : 3
    test1 : 2
    test1 : 1
    test1 : 0
    test2 : 4
    test2 : 3
    test2 : 2
    test2 : 1
    test2 : 0
    //Verification: different instances access the static synchronized method, and the lock works, resulting in blocking

2. In addition to using the synchronized keyword before the method, the synchronized keyword can also be used in a block of the method, indicating that only the resources of this block are mutually exclusive. Usage: synchronized(this) {/ block /} (or synchronized(obj) {/ block /}), whose scope is the current object;

3. The synchronized keyword cannot be inherited, that is to say, the method synchronized f() {} of the base class does not automatically synchronize f() {} in the inherited class, but becomes f() {}. Inheritance class requires you to explicitly specify one of its methods as synchronized

Some understanding of synchronized(this)

1, (premise of the same instance object) when two concurrent threads access the synchronized(this) synchronized code block in the same object object, only one thread can be executed in one time, and the other thread must wait for the current thread to finish executing the code block before executing the code block. At the same time, one thread accesses the synchronized(this) synchronized code block, and the other thread accesses the synchronized(this) synchronized code block The program cannot access the synchronized(this) synchronization block or the synchronized method until the lock is released.

public static void main(String[] args)
{
    final TestSync myt1 = new TestSync();
    final TestSync myt2 = new TestSync();
    Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test1();  }  }, "test1"  );
    Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test1();   }  }, "test2"  );
    test1.start();
    test2.start();

}
//Execution result:
test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
test2 : 4
test2 : 3
test2 : 2
test2 : 1
test2 : 0


public static void main(String[] args)
{
    final TestSync myt1 = new TestSync();
    final TestSync myt2 = new TestSync();
    Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test1();  }  }, "test1"  );
    Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test2();   }  }, "test2"  );
    test1.start();
    test2.start();

}
//Execution result:
test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
test2 : 4
test2 : 3
test2 : 2
test2 : 1
test2 : 0

2, (premise: the same instance object or different instances can be used) however, when a thread accesses a synchronized(this) synchronized code block of the object, another thread can still access the non synchronized(this) synchronized code block or non synchronized method in the object

public static void main(String[] args)
{
    final TestSync myt1 = new TestSync();
    final TestSync myt2 = new TestSync();
    Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test1();  }  }, "test1"  );
    Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test5();   }  }, "test2"  );
    test1.start();
    test2.start();

}
//Execution result:
test2 : 4
test1 : 4
test1 : 3
test2 : 3
test1 : 2
test2 : 2
test1 : 1
test2 : 1
test2 : 0
test1 : 0

3, Especially, when a thread accesses a synchronized(this) synchronized code block of an object, the access of other threads to all other synchronized(this) synchronized code blocks in the object will be blocked, and the synchronized method will also be blocked.

public static void main(String[] args)
{
    final TestSync myt1 = new TestSync();
    final TestSync myt2 = new TestSync();
    Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test1();  }  }, "test1"  );
    Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test1();   }  }, "test2"  );
    test1.start();
    test2.start();

}
//Execution result:
test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
test2 : 4
test2 : 3
test2 : 2
test2 : 1
test2 : 0


public static void main(String[] args)
{
    final TestSync myt1 = new TestSync();
    final TestSync myt2 = new TestSync();
    Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test1();  }  }, "test1"  );
    Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test2();   }  }, "test2"  );
    test1.start();
    test2.start();

}
//Execution result:
test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
test2 : 4
test2 : 3
test2 : 2
test2 : 1
test2 : 0

4, The third example is also applicable to other synchronization code blocks. That is to say, when a thread accesses a synchronized(this) synchronized code block of an object, it obtains the object lock of the object. As a result, access of other threads to all synchronized code parts of the object object is temporarily blocked. Note: the static synchronized method is not affected and can still be executed

public static void main(String[] args)
{
    final TestSync myt1 = new TestSync();
    final TestSync myt2 = new TestSync();
    Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test1();  }  }, "test1"  );
    Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test2();   }  }, "test2"  );
    test1.start();
    test2.start();

}
//Execution result:
test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
test2 : 4
test2 : 3
test2 : 2
test2 : 1
test2 : 0


public static void main(String[] args)
{
    final TestSync myt1 = new TestSync();
    final TestSync myt2 = new TestSync();
    Thread test1 = new Thread(  new Runnable() {  public void run() {  myt1.test1();  }  }, "test1"  );
    Thread test2 = new Thread(  new Runnable() {  public void run() { myt1.test4();   }  }, "test2"  );
    test1.start();
    test2.start();

}
//Execution result:
test1 : 4
test2 : 4
test2 : 3
test1 : 3
test2 : 2
test1 : 2
test2 : 1
test1 : 1
test2 : 0
test1 : 0

5, The synchronized decorating method and the synchronized(this) method obtain the lock of the object, with the same effect

6, Synchronized (not this object) synchronization code block

Benefit: if there are many synchronized methods in a class, it is possible to implement synchronization, but it will be blocked. Affect efficiency. However, if a non this lock of a synchronized code block is used, the synchronized (non this) code block and the synchronized synchronization method in the program are asynchronous. Do not fight for this lock with other threads, which can improve the running efficiency.
Use synchronized (any custom object) for synchronization. The object monitor must be the same object. If it is not the same, running is asynchronous.

7, synchronized (class. class)

A class has only one class object, in fact, the class lock is also the object lock of the class. Static methods or code blocks belong to the class (class object), so synchronized decoration of static resources needs to obtain the class lock.
Static modified static methods and static modified static methods have synchronized code blocks to obtain class locks
 synchronized (class. class) modifies non-static code blocks. Instances of all classes, including the class object itself (class. class), are blocked.

Final summary (verified)

Distinguish by single instance or multiple instances

Under the premise of the same instance:

synchronized(this) when the synchronized code block / synchronized method / static synchronized method is executed, the common methods can be executed without mutual exclusion;
synchronized(this) synchronization code block / synchronized method is mutually exclusive;
synchronized(this) synchronized code block / synchronized(this) synchronized code block is mutually exclusive;
synchronized(this) synchronization code block / static synchronized method does not have mutual exclusion;
There is no mutual exclusion between synchronized method and static synchronized method;
There is mutual exclusion between synchronized method and synchronized method;
The static synchronized method and the static synchronized method are mutually exclusive;
synchronized(***.class) has the same effect as the static synchronized method. Lock class
 The synchronized decorated method and the lock obtained with synchronized(this) are the locks of the object

Different examples:

When the synchronized(this) code block / synchronized method / static synchronized method of instance a is executed, it can be executed with the ordinary method of instance b, and there is no mutual exclusion;
There is no mutual exclusion between the synchronized(this) code block of instance a and the synchronized method of instance b;
synchronized(this) synchronized code block of instance a / synchronized(this) synchronized code block of instance b does not exist mutual exclusion;
There is no mutual exclusion between the synchronized(this) code block of instance a and the static synchronized method of instance b;
There is no mutual exclusion between the synchronized method of instance a and the static synchronized method of instance b;
There is no mutual exclusion between the synchronized method of instance a and the synchronized method of instance b;
The static synchronized method of instance a and the static synchronized method of instance b are mutually exclusive;
synchronized(***.class) has the same effect as the static synchronized method. Lock class
 The synchronized decorated method and the lock obtained with synchronized(this) are the locks of the object

Distinguish between synchronized(this) method and static synchronized method

Synchronized method and synchronized(this) mainly work for methods, single instance is mutually exclusive, and multiple instances are not mutually exclusive
 The static synchronized method works for classes, and both single and multiple instances are mutually exclusive
 synchronized(***.class) has the same effect as the static synchronized method. Lock class
 The synchronized decorated method and the lock obtained with synchronized(this) are the locks of the object

Others' summary can be referred to

1. synchronized keyword is mainly used to solve the problem of multithreading concurrent synchronization, which can be used to modify the instance method, static method and code block of a class;

2. The synchronized instance method actually protects the method calls of the same object. When it is a different object, multiple threads can access the same synchronized method at the same time;

3. The synchronized static method and the synchronized instance method protect different objects. Different threads can execute the synchronized static method and the synchronized instance method at the same time. The synchronized static method protects class objects and the synchronized instance method protects this instance objects;

4. Synchronized code blocks can be synchronized with any object, because any object has a lock and wait queue.

5. Synchronized has reentrant property, which can be called directly for the same thread when calling other codes that need the same lock after obtaining the lock. Its reentrant property is realized by recording the holding thread and the number of holding threads of the lock. When calling synchronized code, check whether the object has been locked, check whether it is locked by the current thread, count plus one, or not Join the waiting queue and release the lock until the count is reduced to zero.

6. Synchronized also has memory visibility. In addition to the implementation of atomic operations to avoid race state, it can also be used for methods that are obviously atomic operations (such as the get and set methods of a boolean state variable, state). When the lock is released, all writes will be written back to memory, and the latest data will be read from memory after the lock is obtained; However, for atomic operations, the cost of using synchronized to ensure memory visibility will be higher. The lightweight option should be to use volatile decoration. Once java is decorated, special instructions will be inserted to ensure visibility when the corresponding variables are operated.

7. Synchronized is a heavyweight lock, and its semantic bottom layer is completed by a monitor object. In fact, wait, notify and other methods also depend on the monitor object, so that's why wait, notify and other methods can only be called in synchronized blocks or methods, or else an IllegalMonitorStateException exception will be thrown. Monitor Its essence depends on the Mutex Lock implementation of the underlying operating system, and the switching between threads of the operating system needs to change from the user state to the core state. This cost is very high, and the transition between States takes a relatively long time, so that's why synchronized is inefficient and heavyweight (Java 1.6 is optimized, but compared with other technologies The lock mechanism is still slightly biased.

8. When an exception occurs, synchronized will automatically release the lock resources occupied by the thread. Lock needs to be released actively when the exception occurs. Synchronized cannot respond to the interrupt when the lock is waiting, but lock can.
--------------------- 
Original: https://blog.csdn.net/u010647035/article/details/82320571 

Reference resources

Original: https://blog.csdn.net/liovey/article/details/7456096

Posted by Syphon on Tue, 28 Jan 2020 06:59:34 -0800