Java鎖擦除與鎖粗化概念和使用詳解
一、什么是鎖擦除
鎖擦除是指虛擬機即時編譯器(JIT)在運行時,對一些代碼上要求同步,但是被檢測到不可能存在共享數(shù)據(jù)競爭的鎖進行擦除。鎖擦除的主要判定依據(jù)來源于逃逸分析的數(shù)據(jù)支持,如果判斷在一段代碼中,堆上的所有數(shù)據(jù)都不會逃逸出去從而被其他線程訪問到,那就可以把它們當(dāng)做棧上數(shù)據(jù)對待,認為它們是線程私有的,同步加鎖自然就無須進行。
二、鎖擦除的演示
public class LockErasureDemo {
public static void main(String[] args) {
new Thread(() -> {
String contact = contact("aa", "bb", "cc");
System.out.println(Thread.currentThread().getName() + ":" + contact);
}, "t1").start();
new Thread(() -> {
String contact = contact("dd", "ee", "ff");
System.out.println(Thread.currentThread().getName() + ":" + contact);
}, "t2").start();
}
private static String contact(String s1, String s2, String s3) {
StringBuffer stringBuffer = new StringBuffer();
return stringBuffer.append(s1).append(s2).append(s3).toString();
}
}觀察上面的代碼,我們都知道StringBuffer的append方法是加了synchronized的同步方法:
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}這里鎖住的對象其實就是stringBuffer這個局部變量,因為是局部變量,所以每個線程進來生成的stringBuffer對象不同,相當(dāng)于每個線程自己new了一把鎖,所以這里不存在競爭同一把鎖的問題,JVM底層會將這個鎖進行擦除。
三、什么是鎖粗化
原則上,我們在編寫代碼的時候,總是推薦將同步塊的作用范圍限制得盡量小,只在共享數(shù)據(jù)的實際作用域中才進行同步,這樣是為了使得需要同步的操作數(shù)量盡可能變小,如果存在鎖競爭,那等待鎖的線程也能盡快拿到鎖。大部分情況下,上面的原則都是正確的,但是如果一系列的連續(xù)操作都對同一個對象反復(fù)加鎖和解鎖,甚至加鎖操作是出現(xiàn)在循環(huán)體中的,那即使沒有線程競爭,頻繁地進行互斥同步操作也會導(dǎo)致不必要的性能損耗。
四、鎖粗化的演示
public class LockCoarseningDemo {
static Object objLock = new Object();
public static void main(String[] args) {
// 反復(fù)加鎖、解鎖
new Thread(() -> {
synchronized (objLock) {
System.out.println("a");
}
synchronized (objLock) {
System.out.println("b");
}
synchronized (objLock) {
System.out.println("c");
}
}, "t1").start();
}
}觀察上面的案例,同一個線程對同一把鎖,反復(fù)不斷地獲取鎖、釋放鎖,這樣肯定影響性能。為了避免重復(fù)的加鎖解鎖,JVM可能會將上面的代碼優(yōu)化成下面這樣:
// 鎖粗化: 如果方法中首尾相接,前后相鄰的都是同一個鎖對象,那JIT編譯器就會把這幾個synchronized塊合并成一個大塊
// 加粗加大范圍,一次申請鎖即可,避免多次的申請和釋放鎖,提升性能
new Thread(() -> {
synchronized (objLock) {
System.out.println("a");
System.out.println("b");
System.out.println("c");
}
}, "t1").start();到此這篇關(guān)于Java鎖擦除與鎖粗化概念和使用詳解的文章就介紹到這了,更多相關(guān)Java鎖擦除與鎖粗化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring boot應(yīng)用啟動后首次訪問很慢的解決方案
這篇文章主要介紹了Spring boot應(yīng)用啟動后首次訪問很慢的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
Java線程之線程同步synchronized和volatile詳解
這篇文章主要介紹了Java線程之線程同步synchronized和volatile詳解,具有一定參考價值,需要的朋友可以了解下。2017-11-11
Java 異常的棧軌跡(Stack Trace)詳解及實例代碼
這篇文章主要介紹了Java 異常的棧軌跡(Stack Trace)詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
idea?springBoot項目自動注入mapper為空報錯的解決方法
這篇文章主要介紹了idea?springBoot項目自動注入mapper為空報錯的解決方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03
SpringBoot快速搭建web項目詳細步驟總結(jié)
這篇文章主要介紹了SpringBoot快速搭建web項目詳細步驟總結(jié) ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12
關(guān)于Java鎖性能提高(鎖升級)機制的總結(jié)
這篇文章主要介紹了關(guān)于Java鎖性能提高(鎖升級)機制的總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05
IntelliJ IDEA修改內(nèi)存大小,使得idea運行更流暢
今天小編就為大家分享一篇關(guān)于IntelliJ IDEA修改內(nèi)存大小,使得idea運行更流暢的文章,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10

