1、synchronizedjava
1.類型安全
(1)對象鎖網絡
對象鎖是做用在實例方法或者一個對象實例上面的數據結構
一個類能夠有多個實例對象,所以一個類的對象鎖可能會有多個併發
例子:函數
Account account = new Account(); synchronized(account){ .... }
(2)類鎖性能
而類鎖是做用在靜態方法或者Class對象上面的線程
每一個類只有一個Class對象,因此類鎖只有一個翻譯
類鎖只是一個概念上的東西,並非真實存在的,它只是用來幫助咱們理解鎖定的是實例方法仍是靜態方法區別的 指針
例子:
synchronized(Account.class){ .... }
2.synchronizedd的使用:
(1)鎖對象的引用,以及這個鎖保護的代碼塊。
例子:
private Object obj = new Objcet(); publci void test(){ synchronized(obj){ .... } }
(2)若是做用在實例方法上面,鎖就是該方法所在的當前對象,靜態synchronized方法會從Class對象上得到鎖。
例子:
public synchronized void test(){ .... }
(3)到底是synchronized方法好仍是synchronized代碼塊好呢?
有一個原則就是鎖的範圍越小越好,加鎖的目的就是將鎖進去的代碼做爲原子性操做,由於非原子操做都不是線程安全的,所以synchronized代碼塊應該是在開發過程當中優先考慮使用的加鎖方式。
3.synchronizedd特性
(1)synchronizedd是一種悲觀鎖,也稱爲獨佔鎖,會致使其它全部須要鎖的線程掛起,等待持有鎖的線程釋放鎖。
(2)synchronized不具備繼承性。
若是父類 、子類中存在一樣的方法。父類方法是同步的,子類是不一樣步的。那麼子類的方法就不會沒法繼承父類的方法性質。必須本身加上synchronized關鍵字!
例子:
class A{ public synchronized void test(){ System.out.println("父類"); } } class B extends A{ public void test(){ System.out.println("子類沒法繼承父類的鎖"); } }
(3)重入性
關鍵字synchronized具備鎖重入功能,當一個線程已經持有一個對象鎖後,再次請求該對象鎖時是能夠獲得該對象的鎖的,這種方式是必須的,不然在一個synchronized方法內部就沒有辦法調用該對象的另一個synchronized方法了。鎖重入是經過爲每一個所關聯一個計數器和一個佔有它的線程,當計數器爲0時,認爲鎖是未被佔有的。線程請求一個未被佔有的鎖時,JVM會記錄鎖的佔有者,並將計數器設置爲1。若是同一個線程再次請求該鎖,計數器會遞增,每次佔有的線程退出同步代碼塊時計數器會遞減,直至減爲0時鎖纔會被釋放。
4.實現原理
(1)Java對象頭
synchronized用的鎖是存在Java對象頭裏的,那麼什麼是Java對象頭呢?Hotspot虛擬機的對象頭主要包括兩部分數據:Mark Word(標記字段)、Klass Pointer(類型指針)。
Mark Word(標記字段)
Mark Word用於存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程 ID、偏向時間戳等等。
Klass Pointer(類型指針)
Klass Pointer是對象指向它的類元數據的指針,虛擬機經過這個指針來肯定這個對象是哪一個類的實例,
(2)Monitor Record
Monitor Record 是線程私有的數據結構,每個線程都有一個可用monitor record(監視記錄)列表,同時還有一個全局的可用列表。每個被鎖住的對象都和一個monitor關聯(對象頭的MarkWord中的LockWord指向monitor的起始地址),同時monitor中有一個Owner字段存放擁有該鎖的線程的惟一標識。
Monitor Record 其結構以下:
Owner: 初始時爲NULL表示當前沒有任何線程擁有該monitor record,當線程成功擁有該鎖後保存線程惟一標識,當鎖被釋放時又設置爲NULL;
EntryQ:關聯一個系統互斥鎖(semaphore),阻塞全部試圖鎖住monitor record失敗的線程。
RcThis:表示blocked或waiting在該monitor record上的全部線程的個數
Nest:用來實現重入鎖的計數。
HashCode:保存從對象頭拷貝過來的HashCode值(可能還包含GC age)
Candidate:用來避免沒必要要的阻塞或等待線程喚醒,由於每一次只有一個線程可以成功擁有鎖,若是每次前一個釋放鎖的線程喚醒全部正在阻塞或等待的線程,會引發沒必要要的上下文切換(從阻塞到就緒而後由於競爭鎖失敗又被阻塞)從而致使性能嚴重降低。Candidate只有兩種可能的值0表示沒有須要喚醒的線程1表示要喚醒一個繼任線程來競爭鎖。
同步代碼塊
monitorenter指令插入到同步代碼塊的開始位置,monitorexit指令插入到同步代碼塊的結束位置,JVM須要保證每個monitorenter都有一個monitorexit與之相對應。任何對象都有一個monitor與之相關聯,當且一個monitor被持有以後,他將處於鎖定狀態。線程執行到monitorenter指令時,將會嘗試獲取對象所對應的monitor全部權,即嘗試獲取對象的鎖。
同步方法:
synchronized方法則會被翻譯成普通的方法調用和返回指令如:invokevirtual、areturn指令,在VM字節碼層面並無任何特別的指令來實現被synchronized修飾的方法,而是在Class文件的方法表中將該方法的access_flags字段中的synchronized標誌位置1,表示該方法是同步方法並使用調用該方法的對象或該方法所屬的Class在JVM的內部對象表示Klass作爲鎖對象。
2、ReentrantLock
1.輪詢鎖的和定時鎖
可輪詢和可定時的鎖請求是經過tryLock()方法實現的,和無條件獲取鎖不同. ReentrantLock能夠有靈活的容錯機制.死鎖的不少狀況是因爲順序鎖引發的, 不一樣線程在試圖得到鎖的時候阻塞,而且不釋放本身已經持有的鎖, 最後形成死鎖. tryLock()方法在試圖得到鎖的時候,若是該鎖已經被其它線程持有,則按照設置方式馬上返回,而不是一直阻塞等下去,同時在返回後釋放本身持有的鎖.能夠根據返回的結果進行重試或者取消,進而避免死鎖的發生。
2.公平性
ReentrantLock構造函數中提供公平性鎖和非公平鎖(默認)兩種選擇。所謂公平鎖,線程將按照他們發出請求的順序來獲取鎖,不容許插隊;但在非公平鎖上,則容許插隊:當一個線程發生獲取鎖的請求的時刻,若是這個鎖是可用的,那這個線程將跳過所在隊列裏等待線程並得到鎖。咱們通常但願全部鎖是非公平的。由於當執行加鎖操做時,公平性將講因爲線程掛起和恢復線程時開銷而極大的下降性能。考慮這麼一種狀況:A線程持有鎖,B線程請求這個鎖,所以B線程被掛起;A線程釋放這個鎖時,B線程將被喚醒,所以再次嘗試獲取鎖;與此同時,C線程也請求獲取這個鎖,那麼C線程極可能在B線程被徹底喚醒以前得到、使用以及釋放這個鎖。這是種共贏的局面,B獲取鎖的時刻(B被喚醒後才能獲取鎖)並無推遲,C更早地獲取了鎖,而且吞吐量也得到了提升。在大多數狀況下,非公平鎖的性能要高於公平鎖的性能。
3.可中斷獲鎖獲取操做
lockInterruptibly方法可以在獲取鎖的同時保持對中斷的響應,所以無需建立其它類型的不可中斷阻塞操做。
4.Condition
Lock提供的線程之間交互類:
await:阻塞線程
signal:釋放阻塞的線程
signalAll:釋放全部阻塞的線程
5.ReadWriteLock
(1)ReentrantLock是一種標準的互斥鎖,每次最多隻有一個線程能持有鎖。讀寫鎖不同,暴露了兩個Lock對象,其中一個用於讀操做,而另一個用於寫操做。
(2)ReentrantReadWriteLock
ReentrantReadWriteLock實現了ReadWriteLock接口,構造器提供了公平鎖和非公平鎖兩種建立方式。讀寫鎖適用於讀多寫少的狀況,能夠實現更好的併發性,性能高於重入鎖。
ReadLock:讀鎖
WriteLock:寫鎖
6.ReentrantLock特性
(1)ReentrantLock是可重入的鎖,它不一樣於內置鎖, 它在每次使用都須要顯示的加鎖和解鎖, 並且提供了更高級的特性:公平鎖, 定時鎖, 有條件鎖, 可輪詢鎖, 可中斷鎖. 能夠有效避免死鎖的活躍性問題.ReentrantLock實現了。
(2)ReentrantLock是一種樂觀鎖。
7.實現原理
(1)ReentrantLock的方法都依賴於AbstractQueuedSynchronizer的實現 (AQS)
(2)ReentrantLock的鎖資源以state狀態描述,利用CAS則實現對鎖資源的搶佔,並經過一個CLH隊列阻塞全部競爭線程,在後續則逐個喚醒等待中的競爭線程。ReentrantLock繼承AQS徹底從代碼層面實現了java的同步機制,相對於synchronized,更容易實現對各種鎖的擴展。同時,AbstractQueuedSynchronizer中的Condition配合ReentrantLock使用,實現了wait/notify的功能
部分信息來自網絡