一、復習
偽共享原理以及如何避免 樂觀鎖和悲觀鎖
二、公平鎖與非公平鎖
按照執行緒請求并獲得鎖的時間順序,可以將鎖分為公平鎖和非公平鎖 公平鎖:執行緒獲取鎖的順序是按照執行緒請求鎖的時間早晚來進行劃分的,也就是滿足先到先得的原則; 非公平鎖:執行緒在運行時闖入的,并不是按照先到先得的原則,
1.Java中兩種鎖的實作機制
Reentrant reentrant = new Reentrant(true)代表公平鎖 Reentrant reentrant = new Reentrant(false)代表非公平鎖 如果建構式不傳入引數的話,那么默認就是非公平鎖 在沒有公平性需求的前提下盡量使用非公平鎖,因為公平鎖會帶來額外的開銷,
三、獨占鎖和共享鎖
按照一個資源是否可以同時被多個執行緒持有,或者只能被一個執行緒持有,可以分為獨占鎖和共享鎖,ReetrantLock鎖是一個獨占鎖,同一時間只能由一個執行緒所持有;共享鎖可以由多個執行緒共同 持有,比如:ReadWriteLock. 獨占鎖是一中悲觀鎖,這種必須先加排他鎖才能對資源進行訪問,限制了并發性;共享鎖是一中樂觀鎖,這種放寬了加鎖的條件,允許多個執行緒能夠同時訪問資源,
四、可重入鎖
定義:當一個執行緒要獲取一個被其他執行緒占有的獨占鎖時,該執行緒會被阻塞,那么當一個執行緒獲取它自己已經獲取的鎖時是否會被阻塞起來呢?如果不會阻塞就可以稱為可重入鎖 下面舉一個例子
package com.ruigege.PricipleAnalyzingOfThreadLocalRandom3;
public class Hello {
public static void main(String[] args) {
new Hello().helloB();
}
public synchronized void helloA() {
System.out.println("HelloA");
}
public synchronized void helloB() {
System.out.println("HelloB");
helloA();
}
}

代碼決議:hellB方法呼叫,會先獲取得內置鎖,然后列印輸出,之后呼叫helloA方法,在呼叫之前會先獲取內置鎖,如果內置鎖不是可重入的,那么呼叫執行緒將會一直阻塞, 實際上synchronized內部鎖是一個可重入鎖,可重入鎖的原理是在鎖的內部維護一個執行緒標示,用于標示該鎖目前正在被哪個執行緒占用,然后關聯一個計數器,一開始計數器值為0,說明該鎖沒有被任何執行緒占用,當一個執行緒獲取了該鎖時,計數器的值會變成1,計數器的值會變成1,這時其他執行緒再來獲取該鎖時會發現鎖的所有者不是自己而被阻塞掛起,但是當獲取了該鎖的執行緒再次獲得鎖的時候發現鎖的擁有者時自己,就會把計算器值+1,當釋放鎖后計數器-1,當計數器為0的時候,鎖里面的執行緒標示被重置為null,這時候被阻塞的執行緒會被喚醒來競爭獲取該鎖,
五、自旋鎖
由于Java中的執行緒是與作業系統中的執行緒一一對應的,所以當一個執行緒在獲取鎖(比如獨占鎖)失敗后,會被切換到內核狀態而被掛起,當該執行緒獲取到鎖時又需要將其切換到內核狀態而喚醒該執行緒,而從用戶狀態切換到內核狀態的開銷是比較大的,在一定程度上會影響并發性能,自旋鎖則是,當前執行緒在獲取鎖的時候,如果發現這個鎖已經被其他的鎖占用了,他不能馬上阻塞自己,在不放棄CPU使用權的情況下,多次嘗試獲取(默認次數10,可以使用-XX:PreBlockSpinsh引數設定該值),很有可能在后面幾次嘗試中其他執行緒已經釋放了鎖,如果嘗試指定的次數后仍沒有獲取到鎖則當前執行緒才會被阻塞掛起,由此看來自旋鎖時使用了CPU時間獲取執行緒阻塞與調度的開銷,但是很有可能這些CPU時間白白浪費了,
六、原始碼:
所在包:com.ruigege.OtherFoundationOfConcurrent2 https://github.com/ruigege66/ConcurrentJavaCSDN:https://blog.csdn.net/weixin_44630050 博客園:https://www.cnblogs.com/ruigege0000/ 歡迎關注微信公眾號:傅里葉變換,個人賬號,僅用于技術交流 
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/231298.html
標籤:Java
