亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中鎖的優化方法

發布時間:2021-08-20 03:07:43 來源:億速云 閱讀:177 作者:chen 欄目:云計算

這篇文章主要講解了“java中鎖的優化方法”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“java中鎖的優化方法”吧!

1)鎖消除

概念:JVM在JIT編譯(即時編譯)時,通過對運行上下文的掃描,去除掉那些不可能發生共享資源競爭的鎖,從而節省了線程請求這些鎖的時間。

舉例:
	StringBuffer的append方法是一個同步方法,如果StringBuffer類型的變量是一個局部變量,則該變量就不會被其它線程所使用,即對局部變量的操作是不會發生線程不安全的問題。
	在這種情景下,JVM會在JIT編譯時自動將append方法上的鎖去掉。

2)鎖粗化

概念:將多個連續的加鎖、解鎖操作連接在一起,擴展成一個范圍更大的鎖,即將加鎖的粒度放大。

舉例:在for循環里的加鎖/解鎖操作,一般需要放到for循環外。

3)使用偏向鎖和輕量級鎖

說明:
	1)java6為了減少獲取鎖和釋放鎖帶來的性能消耗,引入了偏向鎖和輕量級鎖。
	2)鎖一共有4種狀態,級別從低到高依次是:無鎖狀態、偏向鎖、輕量級鎖、重量級鎖。
	3)鎖的狀態會隨著競爭情況逐漸升級,并且只可以升級而不能降級。
	
【偏向鎖】

	1)背景:大多數情況下,鎖不僅不存在多線程競爭,而且總是由同一線程多次獲得,為了讓線程獲得鎖的代價更低而引入了偏向鎖。
	
	2)概念:核心思想就是鎖會偏向第一個獲取它的線程,如果在接下來的執行過程中沒有其它的線程獲取該鎖,則持有偏向鎖的線程永遠不需要同步。
	
	3)目的:偏向鎖實際上是一種優化鎖,其目的是為了減少數據在無競爭情況下的性能損耗。
	
	4)原理:
		1>當一個線程訪問同步塊并獲取鎖時,會在對象頭和棧幀中的鎖記錄里存儲鎖偏向的線程ID。
		2>以后該線程在進入和退出同步塊時就不需要進行CAS操作來加鎖和解鎖,只需簡單地判斷一下對象頭的Mark Word里是否存儲著指向當前線程的偏向鎖。
	
	5)偏向鎖的獲取:
		1>訪問Mark Word中偏向鎖的標識位是否為1,如果是1,則確定為偏向鎖。
			說明:
				[1]如果偏向鎖的標識位為0,說明此時是處于無鎖狀態,則當前線程通過CAS操作嘗試獲取偏向鎖,如果獲取鎖成功,則將Mark Word中的偏向線程ID設置為當前線程ID;并且將偏向標識位設為1。
				[2]如果偏向鎖的標識位不為1,也不為0(此時偏向鎖的標識位沒有值),說明發生了競爭,偏向鎖已經膨脹為輕量級鎖,這時使用CAS操作嘗試獲得鎖。
				
		2>如果是偏向鎖,則判斷Mark Word中的偏向線程ID是否指向當前線程,如果偏向線程ID指向當前線程,則表明當前線程已經獲取到了鎖;
		
		3>如果偏向線程ID并未指向當前線程,則通過CAS操作嘗試獲取偏向鎖,如果獲取鎖成功,則將Mark Word中的偏向線程ID設置為當前線程ID;
		
		4>如果CAS獲取偏向鎖失敗,則表示有競爭。當到達全局安全點時(在這個時間點上沒有正在執行的字節碼),獲得偏向鎖的線程被掛起,偏向鎖升級為輕量級鎖,然后被阻塞在安全點的線程繼續往下執行同步代碼。
	
    6)偏向鎖的釋放:  
        1>當其它的線程嘗試獲取偏向鎖時,持有偏向鎖的線程才會釋放偏向鎖。  
        2>釋放偏向鎖需要等待全局安全點(在這個時間點上沒有正在執行的字節碼)。 
		3>過程:
			首先暫停擁有偏向鎖的線程,然后檢查持有偏向鎖的線程是否活著,如果線程不處于活動狀態,則將對象頭設置成無鎖狀態,
			如果線程還活著,說明此時發生了競爭,則偏向鎖升級為輕量級鎖,然后剛剛被暫停的線程會繼續往下執行同步代碼。
	
	7)優點:加鎖和解鎖不需要額外的消耗,和執行非同步方法相比僅存在納秒級的差距

	8)缺點:如果線程間存在鎖競爭,鎖撤銷會帶來額外的消耗。
	
	9)說明:
		1)偏向鎖默認在應用程序啟動幾秒鐘之后才激活。
		2)可以通過設置 -XX:BiasedLockingStartupDelay=0 來關閉延遲。
		3)可以通過設置 -XX:-UseBiasedLocking=false 來關閉偏向鎖,程序默認會進入輕量級鎖狀態。(如果應用程序里的鎖大多情況下處于競爭狀態,則應該將偏向鎖關閉)
	

【輕量級鎖】  
	1)原理:
		1>當使用輕量級鎖(鎖標識位為00)時,線程在執行同步塊之前,JVM會先在當前線程的棧楨中創建用于存儲鎖記錄的空間,并將對象頭中的Mark Word復制到鎖記錄中(注:鎖記錄中的標識字段稱為Displaced Mark Word)。
		
		2>將對象頭中的MarkWord復制到棧楨中的鎖記錄中之后,虛擬機將嘗試使用CAS將對象頭中Mark Word替換為指向該線程虛擬機棧中鎖記錄的指針,此時如果沒有線程占有鎖或者沒有線程競爭鎖,則當前線程成功獲取到鎖,然后執行同步塊中的代碼。
		
		3>如果在獲取到鎖的線程執行同步代碼的過程中,另一個線程也完成了棧楨中鎖記錄的創建,并且已經將對象頭中的MarkWord復制到了自己的鎖記錄中,然后嘗試使用CAS將對象頭中的MarkWord修改為指向自己的鎖記錄的指針,但是由于之前獲取到鎖的線程已經將對象頭中的MarkWord修改過了(并且現在還在執行同步體中的代碼,即仍然持有著鎖),所以此時對象頭中的MarkWord與當前線程鎖記錄中MarkWord的值不同,導致CAS操作失敗,然后該線程就會不停地循環使用CAS操作試圖將對象頭中的MarkWord替換為自己鎖記錄中MarkWord的值,(當循環次數或循環時間達到上限時停止循環)如果在循環結束之前CAS操作成功,那么該線程就可以成功獲取到鎖,如果循環結束之后依然獲取不到鎖,則鎖獲取失敗,對象頭中的MarkWord會被修改為指向重量級鎖的指針,然后這個獲取鎖失敗的線程就會被掛起,阻塞了。
		
		4>當持有鎖的那個線程執行完同步體之后,使用CAS操作將對象頭中的MarkWord還原為最初的狀態時(將對象頭中指向鎖記錄的指針替換為Displaced Mark Word ),發現MarkWord已被修改為指向重量級鎖的指針,因此CAS操作失敗,該線程會釋放鎖并喚起阻塞等待的線程,開始新一輪奪鎖之爭,而此時,輕量級鎖已經膨脹為重量級鎖,所有競爭失敗的線程都會阻塞,而不是自旋。

        自旋鎖:  
            1)所謂自旋鎖,就是讓沒有獲得鎖的進程自己運行一段時間自循環(默認開啟),但是不掛起線程。  
            2)自旋的代價就是該線程會一直占用處理器如果鎖占用的時間很短,自旋等待的效果很好,反之,自旋鎖會消耗大量處理器資源。  
            3)因此,自旋的等待時間必須有一定限度,超過限度還沒有獲得鎖,就要掛起線程。  

    優點:在沒有多線程競爭的前提下,減少傳統的重量級鎖帶來的性能損耗。  
      
    缺點:競爭的線程如果始終得不到鎖,自旋會消耗cpu。  

    應用:追求響應時間,同步塊執行速度非常快。  
      
      
【重量級鎖】  

	說明:
		1)java6之前的synchronized屬于重量級鎖,效率低下,因為monitor是依賴操作系統的Mutex Lock(互斥量)來實現的。
		2)多線程競爭鎖時,會引起線程的上下文切換(即在cpu分配的時間片還沒有用完的情況下進行了上下文切換)。
		3)操作系統實現線程的上下文切換需要從用戶態轉換到核心態,這個狀態之間的轉換需要相對較長的時間,時間成本相對較高。
		4)在互斥狀態下,沒有得到鎖的線程會被掛起阻塞,而掛起線程和恢復線程的操作都需要從用戶態轉入內核態中完成。

	優點:線程競爭不使用自旋,不會消耗cpu。
	
	缺點:線程阻塞,響應時間緩慢。
	
	應用:追求吞吐量,同步塊執行速度較長

感謝各位的閱讀,以上就是“java中鎖的優化方法”的內容了,經過本文的學習后,相信大家對java中鎖的優化方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

南丹县| 信宜市| 和硕县| 洛浦县| 穆棱市| 海门市| 普兰店市| 康保县| 岳池县| 怀宁县| 靖边县| 邵东县| 武清区| 桓台县| 建瓯市| 隆化县| 长兴县| 布拖县| 怀安县| 兴安盟| 鸡东县| 卫辉市| 商水县| 门源| 阜阳市| 美姑县| 贵港市| 桓仁| 新野县| 台前县| 桐城市| 汝南县| 延安市| 阜新市| 湟中县| 三台县| 吉林市| 彰化市| 潞城市| 大埔区| 恭城|