synchronized optimization principle


1. Monitor

Monitor的工作原理也是synchronized底层原理
Each Java object can be associated with a Monitor object. If the synchronizedobject is locked, the MarkWord in the object header will be set with a pointer to the Monitor object.

1.1 Monitor structure

Insert image description here

  1. When multiple threads are executed synchronized临界区代码, if Thread2 seizes the right to use, then the Owner in the Monitor object points to Thread2
  2. When other threads are executed synchronized, they find that obj has been associated with a Monitor lock. Check whether the owner of the Monitor lock is locked. Then it Monitor中的Ownerpoints to Thread2 at this time, so other threads cannot obtain the lock. Then the thread that cannot obtain the lock will contact EntryList(可以把EntryList理解为等待队列)Association in monitor lock
  3. When the Thread2 thread of the Owner in the Monitor lock will synchronized临界区代码complete execution, the Owner in the Monitor lock will be free, and the 通知Monitor锁中EntryListwaiting thread will be awakened. After waking up, the waiting thread will 竞争go to compete synchronized临街区代码for the execution right, and will obtain synchronized临街区代码the execution right. The thread is placed in the Owner of the Monitor lock

2. Lightweight lock

Usage scenarios of lightweight locks: If an object is accessed by multiple threads, but the access times of the multiple threads are staggered (that is, there is no competition), then you can使用轻量级锁来优化
轻量级锁对使用者是透明的,即语法仍然是synchronized

Suppose there are two methods to synchronize blocks and use the same object to lock

static final Object obj=new Object();
public static void method1(){
    
    
	synchronized(obj){
    
    
		//同步块A
		method2();
	}
	
}
public static void method2(){
    
    
	synchronized(obj){
    
    
		//同步块B

	}
}
  1. Create 锁记录(Lock Record)对象,它是JVM层面的, the stack frame of each thread will contain a lock record structure, which can store the lock object internally.Mark Word
    状态00 可以理解为 轻量级锁
    状态01 可以理解为 正常状态(未加锁)
    Insert image description here

  2. When thread T0 executes the method1 method to lock the object, 让T0线程中的Object reference指向锁对象and 尝试CASreplaces the value in Object Mark Word, the value of Mark Word is stored in the T0 thread.锁记录
    状态00 可以理解为 轻量级锁
    状态01 可以理解为 正常状态(未加锁)
    Insert image description here

  3. If T0线程CAS替换成功, Object对象头中it is stored T0线程的锁记录地址和状态00, it means that the thread locks the object, as shown in the figure

    状态00 可以理解为 轻量级锁
    Insert image description here

  4. If CAS fails in step 3, there are two situations
    4.1. If 其他线程已经持有yes Object的轻量级锁, then it indicates 有竞争that, enter 锁膨胀过程
    4.2. If yes 自己执行了synchronized锁重入(可以理解为加锁的方法1,又调用了加锁的方法2,加锁的是同一个obj), then 再添加一条Lock Recordas重入的计数
    Insert image description here

  5. When exiting synchronized代码块(解锁时), if T0线程有取值为null, 锁记录means 有重入, then reset the lock record, means重入计数减一
    Insert image description here

  6. When 退出synchronized代码块(解锁时)the value of the lock record is used 不为null, if 6.1 succeeds, the unlocking succeeds and 6.2 fails, indicating that the lightweight lock has undergone lock expansion or has been upgraded to a heavyweight lock, and enters the heavyweight lock unlocking process.T0线程CASMark Word的值恢复给Object对象头

3. Lock expansion

If the operation fails 尝试加轻量级锁的过程中, CASthis is a situation where other threads have added this object 轻量级锁(有竞争). At this time, it is necessary 锁膨胀to change the lightweight lock into a heavyweight lock.

static Object obj=new Object();
public static void method1(){
    
    
	synchronized(obj){
    
    
		//同步块
	}
	
}
  1. When T1线程performing lightweight locking, T0线程a lightweight lock has been added to the object.
    此时Object中Mark Word的状态是10,代表的是重量级锁
    Insert image description here
  2. At this time, T1 fails to add a lightweight lock, and enters the expansion lock process
    2.1, which is to apply for a Monitor lock for the Object object, let the Object point to the heavyweight lock address
    2.2, and then enter the Monitor's EntryList to become blocked.
    Insert image description here
  3. When the T0 thread exits the synchronized block unlocking (at this time, the T0 thread adds the object to the object 轻量级锁), the use CAS将Mark Word的值恢复给Object的对象头fails. At this time, you will enter 重量级解锁流程, that is,按照Monitor地址找到Monitor对象,设置Owner为null,唤醒EntryList中的blocked线程

4. Spin optimization

  1. Spin success situation: 重量级锁竞争When, you can also use it CAS自旋for optimization. If the current thread 自旋成功(that is, the lock-holding thread has exited the synchronization block and released the lock at this time), then 当前线程you can避免阻塞
  2. Spin failure situation: if 线程执行synchronized同步块迟迟不解锁, B线程自旋重试几次之后,没有获取到锁,那么B线程就会进入Monitor的EntryList进入变成blocked状态

5. Bias lock

轻量级锁In 没有竞争时(just this thread), 每次重入it is still needed 执行CAS操作. Introduced in Java 6 偏向锁to go further 优化: only 第一次使用CAS将线程ID设置到Object的Mark Word头, later discovered 这个线程ID是自己的就表示没有竞争, no need to re- CAS. As long as no competition occurs in the future, this object will be owned by the thread.

static final Object obj=new Object();
public static void method1(){
    
    
	synchronized(obj){
    
    
		//同步块A
		method2();
	}
	
}
public static void method2(){
    
    
	synchronized(obj){
    
    
		//同步块B
		method3();
	}
}
public static void method3(){
    
    
	synchronized(obj){
    
    
		//同步块C
		
	}
}

Illustration: When there is no competition, the T0 thread executes the m1 method to execute synchronized(obj), and will replace the ThreadID with the MarkWord in the Object header. m1 calls the m2 method again, and m2 executes synchronized(obj), and will check the Object object header. Whether the ThreadID is its current thread, m2 calls the m3 method again, m3 executes synchronized(obj), and will check whether the ThreadID in the Object object header is its current thread, then there is no need to perform CAS to try to replace it.
Insert image description here

Guess you like

Origin blog.csdn.net/m0_50677223/article/details/130714070