Analysis of the usage and usage scenarios of synchronized programming

The purpose of life is to grow, the essence of life is to change, the challenge of life is to conquer
the purpose of life is to grow, the essence of life is change, the challenge of life is to conquer


The synchronized keyword is almost a required question for every interview. Today, let ’s talk about the use of synchronized and its usage scenarios.

As we all know, there are three major characteristics in the Java memory model, atomicity, visibility, and order

synchronized: guarantees visibility and atomicity

In the Java memory model, synchronized stipulates that when a thread is locked, it first clears the working memory-> copies the latest variable copy from the main memory to the working memory-> executes the code-> changes the shared variables The value is refreshed into the main memory-> release the mutex

Ordering: The natural ordering in a Java program can be summarized in one sentence. If you observe in this thread, all operations are naturally ordered, and if you observe another thread in one thread, all operations are out of order. of

Synchronized allows variables or code blocks to be accessed by only one thread at a time, reducing memory consumption. What is locked is an instance of an object, an instance that exists in the heap, not a code block. Other threads must wait for this object to use it This object can only be obtained when it is released, so the synchronized thought can also be understood as a pessimistic lock

And look at the singleton mode with double check lock below

     private volatile static Singleton singleton;

     public static Singleton getSingleton(){    
        if(null == singleton){        
           synchronized (Singleton.class) {            
              if(null == singleton){                
                   singleton = new Singleton();            
              }        
           }    
         }
         return singleton;
     }

     public static void main(String[] args) {    
       for(int i = 0;i<10;i++){        
          new Thread(new Runnable() {            
          @Override            
          public void run() {                
              System.out.println(Thread.currentThread().getName()+":"+Singleton.getSingleton().hashCode());            
          }}).start();    
     }复制代码


As you can see, the object Singleton has been modified with volatile, and it has been judged twice again. Modified visibility has been implemented with volatile modification (volatile is also a keyword). The two judgements are because the first judgement was The singleton mode only needs to create an instance, and if it is called again later, it will directly return to the previously created instance, so most of the time, there is no need to execute the code in the synchronization method, which greatly improves performance. The second judgment is that it is assumed that after thread 1 performs the first verification, at this time, thread 2 also acquires cpu execution rights. Next, thread 2 acquires a lock and creates an instance. At this time, thread 1 obtains execution authority and also creates an instance. As a result, multiple instances will be created , so you need to perform a second check in the synchronization code. If the instance is empty, then create it again, so that only one object is created.

synchronized can be added to the method can also be added to the code block

class Sync{
     public synchronized void test() {          
         System.out.println("test开始..");          
         
         try {              
             Thread.sleep(1000);          
         } catch (InterruptedException e) {             
             e.printStackTrace();          
         }          
             System.out.println("test结束..");      
      }  
}    

class MyThread extends Thread {        

     public void run() {          
        Sync sync = new Sync();          
        sync.test();      
     }  
}   
 
public class Main {        
    
      public static void main(String[] args) {          
          for (int i = 0; i < 3; i++) {              
             Thread thread = new MyThread();              
             thread.start();          
          }      
      }  
} 
} 复制代码

operation result:

test start ... test start ... test start ... test end ... test end ... test end ...

There has been no change, and I have not seen synchronized play a role

Then we try to add synchronized to the code block to reduce the granularity of the lock

class Sync {        

      public void test() {          
         synchronized (Sync.class) {              
              System.out.println("test开始..");              
         
         try {                  
              Thread.sleep(1000);              
         } catch (InterruptedException e) {                 
              e.printStackTrace();              
         }              
         System.out.println("test结束..");          
      }      
}  
}    


class MyThread extends Thread {        
      public void run() {          
          Sync sync = new Sync();          
          sync.test();      
      }  
}   


public class Main {        
     
        public static void main(String[] args) {         
        
           for (int i = 0; i < 3; i++) {              
               Thread thread = new MyThread();              
               thread.start();          
           }      
        }  
}  复制代码

运行结果: 
test开始.. test结束.. test开始.. test结束.. test开始.. test结束..复制代码

It can be seen that the synchronized lock is not this, but the Class Class object

Synchronized reentrancy

syncronized is an internal locking mechanism based on atomicity and is reentrant
A thread calls the synchronized method while calling another synchronized method of the object within its method body
When the subclass inherits the parent class, the subclass can also call the synchronization method of the parent class through the reentrant lock

to sum up

Synchronized lock is either an instance of the class, or the object passed in, or that sentence, synchronized so that variables or code blocks can only be accessed by one thread at a time


Guess you like

Origin juejin.im/post/5e8ecce9f265da48027a2763