Java鎖優(yōu)化

Java鎖優(yōu)化

應(yīng)用程序在并發(fā)環(huán)境下會產(chǎn)生很多問題帝璧,通常情況下避除,我們可以通過加鎖來解決多線程對臨界資源的訪問問題逆航。但是加鎖往往會成為系統(tǒng)的瓶頸宠能,因為加鎖和釋放鎖會涉及到與操作系統(tǒng)的交互刃滓,會有很大的性能問題寡润。那么這個時候基于鎖的優(yōu)化手段就顯得很重要了赴邻。

一般情況下书闸,可以從兩個角度進行鎖優(yōu)化:對單個鎖算法的優(yōu)化和對鎖粒度的細分审胸。

1. 單個鎖的優(yōu)化

自旋鎖:

? 非自旋鎖在未獲取鎖的情況會被阻塞亥宿,之后再喚醒嘗試獲得鎖。而JDK的阻塞和喚醒是基于操作系統(tǒng)實現(xiàn)的歹嘹,會有系統(tǒng)資源的開銷箩绍。自旋鎖就是線程不停地循環(huán)嘗試獲得鎖,而不會將自己阻塞尺上,這樣不會浪費系統(tǒng)的資源開銷材蛛,但是會浪費CPU的資源圆到。所有現(xiàn)在的JDK大部分都是先自旋等待,如果自旋等待一段時間之后還沒有獲取到鎖卑吭,就會將當(dāng)前線程阻塞芽淡。

鎖消除:

? 當(dāng)JVM分析代碼時發(fā)現(xiàn)某個方法只被單個線程安全訪問,而且這個方法是同步方法豆赏,那么JVM就會去掉這個方法的鎖挣菲。

單個鎖優(yōu)化的瓶頸:

? 對單個鎖優(yōu)化的效果就像提高單個CPU的處理能力一樣,最終會由于各個方面的限制而達到一個平衡點掷邦,到達這個點之后優(yōu)化單個鎖的對高并發(fā)下面鎖的優(yōu)化效果越來越低白胀。所以將一個鎖進行粒度細分帶來的效果會很明顯,如果一個鎖保護的代碼塊被拆分成兩個鎖來保護抚岗,那么程序的效率就大約能夠提高到2倍或杠,這個比單個鎖的優(yōu)化帶來的效果要明顯很多。常見的鎖粒度細分技術(shù)有:鎖分解和鎖分段

2. 細分鎖粒度

細分鎖粒度的目的是降低競爭鎖的概率宣蔚。

2.1 鎖分解

鎖分解的核心是將無關(guān)的代碼塊向抢,如果在一個方法中有一部分的代碼與鎖無關(guān),一部分的代碼與鎖有關(guān)胚委,那么可以縮小這個鎖的返回挟鸠,這樣鎖操作的代碼塊就會減少,鎖競爭的可能性也會減少

縮小鎖的范圍

縮小鎖的范圍是指盡量只在必要的地方加鎖亩冬,不要擴大加鎖的范圍艘希,就拿單例模式舉例,范圍大的鎖可能將整個方法都加鎖了:

class Singleton {
  private Singleton instance;

  private Singleton() {
  }

  // 將整個方法加鎖
  public synchronized Singleton getInstance() {
    try {
      Thread.sleep(1000);  //do something
      if(null == instance)
        instance = new Singleton();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    return instance;
  }

}

優(yōu)化后的鉴未,只將部分代碼加鎖:

class Singleton {
  private Singleton instance;

  private Singleton() {
  }

  public Singleton getInstance() {
    try {
      Thread.sleep(1000);  //do something
      // 只對部分代碼加鎖
      synchronized(this) {
        if(null == instance)
          instance = new Singleton();
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    return instance;
  }
}

減少鎖的粒度

減少鎖的粒度是指如果一個鎖需要保護多個相互獨立的變量枢冤,那么可以將一個鎖分解為多個鎖鸠姨,并且每個鎖保護一個變量铜秆,這樣就可以減少鎖沖突⊙惹ǎ看一下下面的例子:

class Demo{
  private Set<String> allUsers = new HashSet<String>();
  private Set<String> allComputers = new HashSet<String>();

  //公用一把鎖
  public synchronized void addUser(String user){ 
    allUsers.add(user);
  }

  public synchronized void addComputer(String computer){
    allComputers.add(computer);
  }
}

縮小鎖的粒度后连茧,將一個鎖拆分為多個:

class Demo{
  private Set<String> allUsers = new HashSet<String>();
  private Set<String> allComputers = new HashSet<String>();

  //分解為兩把鎖
  public void addUser(String user){ 
    synchronized (allUsers){
      allUsers.add(user);
    }
  }

  public void addComputer(String computer){
    synchronized (allComputers){
      allComputers.add(computer);
    }
  }
}

如上的方法把一個鎖分解為2個鎖時候,采用兩個線程時候巍糯,大約能夠使程序的效率提升一倍啸驯。

2.2 鎖分段

鎖分段和縮小鎖的粒度類似,就是將鎖細分的粒度更多祟峦,比如將一個數(shù)組的每個位置當(dāng)做單獨的鎖罚斗。JDK8以前ConcurrentHashMap就使用了鎖分段技術(shù),它將散列數(shù)組分成多個Segment宅楞,每個Segment存儲了實際的數(shù)據(jù)针姿,訪問數(shù)據(jù)的時候只需要對數(shù)據(jù)所在的Segment加鎖就行袱吆。

參考:

Java鎖分解鎖分段技術(shù): http://guochenglai.com/2016/06/04/java-concurrent4-java-subsection-decompose/

ConcurrentHashMap的鎖分段技術(shù):https://blog.csdn.net/yansong_8686/article/details/50664351

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市距淫,隨后出現(xiàn)的幾起案子绞绒,更是在濱河造成了極大的恐慌,老刑警劉巖榕暇,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蓬衡,死亡現(xiàn)場離奇詭異,居然都是意外死亡彤枢,警方通過查閱死者的電腦和手機狰晚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缴啡,“玉大人家肯,你說我怎么就攤上這事∶瞬” “怎么了讨衣?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長式镐。 經(jīng)常有香客問我反镇,道長,這世上最難降的妖魔是什么娘汞? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任歹茶,我火速辦了婚禮,結(jié)果婚禮上你弦,老公的妹妹穿的比我還像新娘惊豺。我一直安慰自己,他們只是感情好禽作,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布尸昧。 她就那樣靜靜地躺著,像睡著了一般旷偿。 火紅的嫁衣襯著肌膚如雪烹俗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天萍程,我揣著相機與錄音幢妄,去河邊找鬼。 笑死茫负,一個胖子當(dāng)著我的面吹牛蕉鸳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播忍法,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼潮尝,長吁一口氣:“原來是場噩夢啊……” “哼无虚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衍锚,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤友题,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后戴质,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體度宦,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年告匠,在試婚紗的時候發(fā)現(xiàn)自己被綠了戈抄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡后专,死狀恐怖划鸽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情戚哎,我是刑警寧澤裸诽,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站型凳,受9級特大地震影響丈冬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甘畅,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一埂蕊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疏唾,春花似錦蓄氧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至准给,卻和暖如春泄朴,著一層夾襖步出監(jiān)牢的瞬間重抖,已是汗流浹背露氮。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钟沛,地道東北人畔规。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像恨统,于是被迫代替她去往敵國和親叁扫。 傳聞我的和親對象是個殘疾皇子三妈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 某天,A同學(xué)給大家分享Java鎖優(yōu)化莫绣,大致內(nèi)容類似Java鎖優(yōu)化畴蒲,有興趣的看客大大們可以跳過去了解一波。对室。模燥。 Ho...
    黑山老妖拉肚子閱讀 10,885評論 2 20
  • 在一個方法內(nèi)部定義的變量都存儲在棧中,當(dāng)這個函數(shù)運行結(jié)束后掩宜,其對應(yīng)的棧就會被回收蔫骂,此時,在其方法體中定義的變量將不...
    Y了個J閱讀 4,418評論 1 14
  • 之前做過一個測試牺汤,詳情見這篇文章《多線程 +1操作的幾種實現(xiàn)方式辽旋,及效率對比》,當(dāng)時對這個測試結(jié)果很疑惑檐迟,反復(fù)執(zhí)行...
    bbe9e62bc5ba閱讀 1,777評論 2 68
  • 從三月份找實習(xí)到現(xiàn)在补胚,面了一些公司,掛了不少追迟,但最終還是拿到小米糖儡、百度、阿里怔匣、京東握联、新浪、CVTE每瞒、樂視家的研發(fā)崗...
    時芥藍閱讀 42,254評論 11 349
  • 自我覺察: 語言 具體事項: 中午親戚來家里聚餐金闽,姨媽讓我從外面回來看她的孫子。在看孫子的過程中剿骨,小家伙一直光著身...
    WalkingRoses閱讀 609評論 4 0