current position:Home>Audio and video development journey (53) - synchronized Java Concurrent Programming

Audio and video development journey (53) - synchronized Java Concurrent Programming

2022-01-27 03:50:55 Audio and video development journey

Catalog

  1. synchronized How to use
  2. synchronized Principle
  3. Thread waiting 、 Interrupt and wake up
  4. Information
  5. Harvest

One 、synchronized How to use

keyword synchronized Can guarantee at the same time , Only one thread can execute a method or a block of code . There are three common uses :

  • Decorated instance method , Locks on the current instance , Obtain the lock for the current instance before entering the synchronized code

     synchronized void syncIncrease4Obj(){
            i++;
    }
     Copy code 
  • Modified static method , Locks on the current class object , Acquire the lock for the current class object before entering the synchronization code

    synchronized static void syncIncrease(){
            i++;
    }
     Copy code 
  • Decorated code block , Specify the lock object , Lock a given object , Get the lock of the given object before entering the synchronization code base .
    The method body may be relatively large , At the same time, there are some time-consuming operations , And there's only a small part of the code that needs to be synchronized , If you synchronize the entire method directly , It may not be worth the trouble , At this time, we can use the synchronous code block to wrap the code that needs to be synchronized

    public void syncIncrease(){ synchronized (this){ i++; } }

Two 、 synchronized Principle

2.1 Look at the disassembly code

adopt javap View the generated class File discovery , Imposed synchronized The implementation of the code block uses monitorenter and monitorexit Instructions . The synchronization method relies on modifiers ACC_SYNCHRONIZED To complete .

Let's take a look at synchronized Disassembly of modifier methods

    public static synchronized void increase(){
        i++;
    }

    public synchronized void increase4Obj(){
        i++;
    }
 Copy code 

---> javap -c -v Main.class Decompile the corresponding assembly as follows :

public static synchronized void syncIncrease();
   descriptor: ()V
   flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED  // Synchronous marking 
   Code:
     stack=2, locals=0, args_size=0
        0: getstatic     #2                  // Field i:I
        3: iconst_1
        4: iadd
        5: putstatic     #2                  // Field i:I
        8: return
     LineNumberTable:
       line 12: 0
       line 13: 8

 public synchronized void syncIncrease4Obj();
   descriptor: ()V
   flags: ACC_PUBLIC, ACC_SYNCHRONIZED.        // Synchronous marking 
   Code:
     stack=2, locals=1, args_size=1
        0: getstatic     #2                  // Field i:I
        3: iconst_1
        4: iadd
        5: putstatic     #2                  // Field i:I
        8: return
     LineNumberTable:
       line 19: 0
       line 20: 8
 Copy code 

ACC_SYNCHRONIZED identification , This flag indicates that the method is a synchronization method ,JVM Through the ACC_SYNCHRONIZED Access flag to identify whether a method is declared as a synchronous method , So as to execute the corresponding synchronous call

Let's look at using... As a code block synchronized Decompilation of

   public void syncIncrease(){
        synchronized (this){
            i++;
        }
    }
 Copy code 

-->javap -c Main.class Decompile the corresponding assembly as follows :

public void syncIncrease();
    Code:
       0: aload_0
       1: dup
       2: astore_1
       3: monitorenter                // Enter synchronization method 
       4: aload_0
       5: dup
       6: getfield      #2                  // Field i:I
       9: iconst_1
      10: iadd
      11: putfield      #2                  // Field i:I
      14: aload_1
      15: monitorexit                 // Exit synchronization method 
      16: goto          24
      19: astore_2
      20: aload_1
      21: monitorexit                 // Exit synchronization method ( This is for exception handling )
      22: aload_2
      23: athrow
      24: return
 Copy code 

Q: As you can see from the bytecode above , One more. monitorexit Instructions , Why? ?
A: To ensure that when the method exception completes monitorenter and monitorexit Instructions can still be executed correctly , The compiler will automatically generate an exception handler , The release executed at the end of the exception monitor Instructions .

Either way , Its essence is the monitor of an object (monitor) Acquisition , And this acquisition is exclusive , That is, only one thread can get synchrozied The monitor protected against sex . Threads that do not get the monitor will be blocked at the entry of the synchronization block or synchronization method , Get into BLOCKED state

The picture is from :《java The art of concurrent programming 》

When executed monitorenter When the command , The current thread will attempt to get objectref( Object lock ) The corresponding monitor The ownership of , When objectref Of monitor The entry counter of is 0, That thread can succeed in monitor, And set the counter value to 1, Lock taken successfully .
If the current thread already has objectref Of monitor The ownership of , Then it can reenter this monitor, The value of the counter will also be added when it is reentered 1.
If other threads already have objectref Of monitor The ownership of the , The current thread will be blocked , Until the executing thread finishes executing , namely monitorexit The instruction was executed

So how do you know if the thread has obtained the monitor of an object ?
Let's study together An object is in JVM Memory layout in , To find out .

2.2 Object head

stay JVM in , The layout of objects in memory is divided into three areas : Object head 、 Instance data and alignment fill .

picture source : In depth understanding of Java Concurrent synchronized Realization principle

Object head : It's the realization of synchronized The foundation of the lock .
Instance variables : Store the attribute data information of the class , Including the attribute information of the parent class , If it is the instance part of the array, it also includes the length of the array , This part is based on 4 Byte alignment
Fill in the data : For byte alignment . The virtual machine requires that the starting address of the object must be 8 Integer multiples of bytes .

Java Head object , It is synchronized The basis of lock object ,synchronized The lock object used is stored in Java The one in the head Mark Word in

The picture is from :《java The art of concurrent programming 》

2.3 Heavyweight lock 、 Biased locking 、 Lightweight lock

2.3.1 Heavyweight lock

stay Java1.6 Before synchronized Only heavyweight locks ,Mark Word The pointer points to monitor object . stay Java virtual machine (HotSpot) in ,monitor By ObjectMonitor Realized , The main data structure is as follows :

ObjectMonitor() {
    _header       = NULL;
    _count        = 0; // Record the number 
    _waiters      = 0,
    _recursions   = 0;
    _object       = NULL;
    _owner        = NULL;
    _WaitSet      = NULL; // be in wait Thread in state , Will be added to _WaitSet
    _WaitSetLock  = 0 ;
    _Responsible  = NULL ;
    _succ         = NULL ;
    _cxq          = NULL ;
    FreeNext      = NULL ;
    _EntryList    = NULL ; // Waiting lock block Thread in state , Will be added to the list 
    _SpinFreq     = 0 ;
    _SpinClock    = 0 ;
    OwnerIsThread = 0 ;
  }
 Copy code 

Monitor lock (monitor) It depends on the underlying operating system Mutex Lock To achieve , While the operating system needs to switch from user state to kernel state when switching between threads , The transition between these States takes a relatively long time , The time cost is relatively high .

Java 6 after , from JVM Face to face synchronized Greater optimization , Introduced lightweight locks and biased locks , Reduce the performance cost of acquiring and releasing locks

2.3.2 Biased locking

The core idea of biased lock is , If a thread gets a lock , Then the lock goes into biased mode , here Mark Word The structure of is also changed to biased lock structure , When the thread requests the lock again , There's no need to do any more synchronization , That is, the process of obtaining the lock , This saves a lot of lock application operations , So that's the performance of the provider

2.3.3 Lightweight lock

Lightweight locks can improve program performance on the basis of “ For most locks , There is no competition throughout the synchronization cycle ”, Note that this is empirical data . What we need to know is , Lightweight locks are suitable for situations where threads execute synchronization blocks alternately , If the same lock is accessed at the same time , It will cause the lightweight lock to expand into the heavyweight lock .

spinlocks

After the lightweight lock fails , Virtual machine in order to avoid threads in the operating system level really hang , There will also be an optimization called spin lock . This is based on... In most cases , The thread will not hold the lock for a long time , If you suspend an operating system level thread directly, it may not pay off , After all, the operating system needs to switch between threads from user state to kernel state , The transition between these States takes a relatively long time , The time cost is relatively high , So spin lock will assume that in the near future , The current thread can get the lock , So the virtual machine lets the thread that wants to acquire the lock do several empty loops ( It's also called spin ), Usually not for long , May be 50 A cycle or 100 loop , After several cycles , If you get a lock , So we can get into the critical zone . If you can't get the lock yet , That will suspend the thread at the operating system level , That's how spin lock is optimized , This way can improve efficiency . In the end, we can only upgrade to heavyweight lock
Quote from : Strongly recommend - In depth understanding of Java Concurrent synchronized Realization principle

Lock elimination

Java Virtual machine in JIT Compile time , By scanning the running context , Remove locks that cannot compete for shared resources , Eliminate unnecessary locks in this way , Can save meaningless request lock time

3、 ... and 、 Thread waiting 、 Interrupt and wake up

3.1 wait for / A notification mechanism

wait for / The relevant method of notification is arbitrary java All the objects have , Because these methods are defined in Object Class

  • notify: Notify a thread waiting on an object , Make it from wait Method returns , and The premise of return is that the thread obtains the lock of the object notify Move a waiting thread in the waiting queue to the synchronization queue , The state of the thread being moved is WAITING become BLOCKED

  • notifyAll: Notify all threads waiting on the object .

  • wait: The thread calling the method enters WAITING state , And put the current thread in the waiting queue of the object . Just wait Another thread notifies or is interrupted Will be returned , We need to pay attention to , call wait After the method , Will release the lock of the object .

  • wait(long): To wait for a period of time , The parameter time here is milliseconds , That is, waiting for a long time n millisecond , Timeout return if no notification

  • Wait(long ,int) Finer control of timeout , Can reach nanoseconds .

When using the above methods , Must be in synchronized Code block or synchronized In the method , Otherwise, it will throw IllegalMonitorStateException abnormal

3.2 Interrupt and wake up

// Interrupt threads ( Example method )
public void Thread.interrupt();

// Determine whether the thread is interrupted ( Example method )
public boolean Thread.isInterrupted();

// Determine whether it is interrupted and clear the current interrupt status ( Static methods )
public static boolean Thread.interrupted();
 Copy code 
  • When a thread is in a blocked state or trying to perform a blocking operation , Use Thread.interrupt() Method to interrupt the thread , Notice that a InterruptedException It's abnormal , At the same time, the interrupt status will be reset ( Change from interrupt state to non interrupt state )

  • When the thread is running , You can also call instance methods interrupt() Interrupt the thread , But at the same time, the interrupt status must be judged manually , And write interrupt thread code ( It's the end of it run Method body code ).

    public static void main(String[] args) throws InterruptedException { Thread t1=new Thread(){ @Override public void run(){ while(true){ // Determine whether the current thread is interrupted if (this.isInterrupted()){ System.out.println(" Thread the interrupt "); break; } }

                System.out.println(" Out of the loop , Thread the interrupt !");
            }
        };
        t1.start();
        TimeUnit.SECONDS.sleep(2);
        t1.interrupt();
    
    }
     Copy code 

Combine the above two points , How can we judge :

public void run(){
    try {
    // Determine whether the current thread has been interrupted , Be careful interrupted The method is static , The interrupt status will be reset after execution 
    while (!Thread.interrupted()) {
        TimeUnit.SECONDS.sleep(2);
    }
    } catch (InterruptedException e) {

    }
}
 Copy code 
  • Thread interrupt operation for the lock object waiting to be acquired synchronized Methods or code blocks don't work . Because the object lock is occupied by other threads , As a result, the waiting thread can only wait until the lock , Now we call thread.interrupt(); But it doesn't interrupt the thread .

Information

  1. The book :《java The art of concurrent programming 》
  2. Strongly recommend - In depth understanding of Java Concurrent synchronized Realization principle

Harvest

Through the study and practice of this article

  1. Reviewed the synchronized Basic use of
  2. To study the synchronized The principle of realizing synchronization
  3. I understand JVM Yes synchronized Do the optimization of the
  4. Learn to review the waiting of threads 、 Interrupt and wake up

Thanks for reading
Next, let's continue to learn about practice Java Concurrent programming series -Lock relevant , Welcome to the official account “ The journey of audio and video development ”, Learn and grow together .
Welcome to exchange

copyright notice
author[Audio and video development journey],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201270350525011.html

Random recommended