Java線程並發中常見的鎖機制詳細介紹_java

來源:互聯網
上載者:User

隨著互連網的蓬勃發展,越來越多的互連網企業面臨著使用者量膨脹而帶來的並發安全問題。本文著重介紹了在java並發中常見的幾種鎖機制。

1.偏向鎖

偏向鎖是JDK1.6提出來的一種鎖最佳化的機制。其核心的思想是,如果程式沒有競爭,則取消之前已經取得鎖的線程同步操作。也就是說,若某一鎖被線程擷取後,便進入偏向模式,當線程再次請求這個鎖時,就無需再進行相關的同步操作了,從而節約了操作時間,如果在此之間有其他的線程進行了鎖請求,則鎖退出偏向模式。在JVM中使用-XX:+UseBiasedLocking

package jvmProject;import java.util.List;import java.util.Vector;public class Biased {  public static List<Integer> numberList = new Vector<Integer>();  public static void main(String[] args) {    long begin = System.currentTimeMillis();    int count = 0;    int startnum = 0;    while(count<10000000){      numberList.add(startnum);      startnum+=2;      count++;        }    long end = System.currentTimeMillis();    System.out.println(end-begin);  }}

初始化一個Vector,往裡面添加10000000個Integer對象,然後輸出時間差。以此來測試偏向鎖的效能。至於為什麼要使用Vector而不使用ArrayList呢?

因為ArrayList是線程不安全的,Vector是安全執行緒的。這樣說可能還不夠具體,可以翻看一下源碼吧。

Vector中的幾乎所有操作是帶有sychronized的,而ArrayList是沒有的,所以Vector是安全執行緒的。

接下來我們來測試一下,開啟偏向鎖和不開啟偏向鎖對程式效能的影響有多大。

配置JVM啟動(開啟偏向鎖)參數為:

配置JVM啟動(關閉偏向鎖)參數為:

Perfect!開啟偏向鎖的程式已耗用時間明顯較短,開啟偏向鎖比不開啟偏向鎖,在單個線程中操作一個對象的同步方法,是有一定的優勢的。其實也可以這樣理解,當只有一個線程操作帶有同步方法的Vector對象的時候,此時對Vector的操作就轉變成了對ArrayList的操作。

偏向鎖在鎖競爭激烈的場合沒有太強的最佳化效果,因為大量的競爭會導致持有鎖的線程不停地切換,鎖也很難保持在偏向模式,此時,使用偏向鎖不僅得不到效能的最佳化,反而有可能降低系統的效能,因此,在激烈競爭的場合,可以嘗試使用

-XX:-UseBiastedLocking參數禁用偏向鎖。

2.輕量級鎖

如果偏向鎖失敗,Java虛擬機器就會讓線程申請輕量級鎖,輕量級鎖在虛擬機器內部,使用一個成為BasicObjectLock的對象實現的,這個對象內部由一個BasicLock對象和一個持有該鎖的Java對象指標組成。BasicObjectLock對象放置在Java棧幀中。在BasicLock對象內部還維護著displaced_header欄位,用於備份對象頭部的Mark Word.

當一個線程持有一個對象的鎖的時候,對象頭部Mark Word資訊如下

[ptr |00] locked

末尾的兩位位元為00,整個Mark Word為指向BasicLock對象的指標。由於BasicObjectLock對象線上程棧中,因此該指標必然指向持有該鎖的線程棧空間。當需要判斷一個線程是否持有該對象時,只需要簡單地判斷對象頭的指標是否在當前線程的棧位址範圍即可。同時,BasicLock對象的displaced_header,備份了原對象的Mark word內容,BasicObjectLock對象的obj欄位則指向持有鎖的對象頭部。

3.重量級鎖

當輕量級鎖失敗,虛擬機器就會使用重量級鎖。在使用重量級鎖的時,對象的Mark Word如下:

[ptr |10] monitor

重量級鎖在操作過程中,線程可能會被作業系統層面掛起,如果是這樣,線程間的切換和調用成本就會大大提高。

4.自旋鎖

自旋鎖可以使線程在沒有取得鎖的時候,不被掛起,而轉去執行一個空迴圈,(即所謂的自旋,就是自己執行空迴圈),若在若干個空迴圈後,線程如果可以獲得鎖,則繼續執行。若線程依然不能獲得鎖,才會被掛起。

使用自旋鎖後,線程被掛起的幾率相對減少,線程執行的連貫性相對加強。因此,對於那些鎖競爭不是很激烈,鎖佔用時間很短的並發線程,具有一定的積極意義,但對於鎖競爭激烈,單線程鎖佔用很長時間的並發程式,自旋鎖在自旋等待後,往往毅然無法獲得對應的鎖,不僅僅白白浪費了CPU時間,最終還是免不了被擱置動作 ,反而浪費了系統的資源。

在JDK1.6中,Java虛擬機器提供-XX:+UseSpinning參數來開啟自旋鎖,使用-XX:PreBlockSpin參數來設定自旋鎖等待的次數。

在JDK1.7開始,自旋鎖的參數被取消,虛擬機器不再支援由使用者配置自旋鎖,自旋鎖總是會執行,自旋鎖次數也由虛擬機器自動調整。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.