ReadWriteLock包括兩種子鎖:
1. ReadWriteLock ReadWriteLock 可以實(shí)現(xiàn)多個(gè)讀鎖同時(shí)進(jìn)行,但是讀與寫(xiě)和寫(xiě)于寫(xiě)互斥,只能有一個(gè)寫(xiě)鎖線程在進(jìn)行。
2. StampedLock StampedLock是Jdk在1.8提供的一種讀寫(xiě)鎖,相比較ReentrantReadWriteLock性能更好,因?yàn)镽eentrantReadWriteLock在讀寫(xiě)之間是互斥的,使用的是一種悲觀策略,在讀線程特別多的情況下,會(huì)造成寫(xiě)線程處于饑餓狀態(tài),雖然可以在初始化的時(shí)候設(shè)置為true指定為公平,但是吞吐量又下去了,而StampedLock是提供了一種樂(lè)觀策略,更好的實(shí)現(xiàn)讀寫(xiě)分離,并且吞吐量不會(huì)下降。
StampedLock包括三種鎖:
1. 寫(xiě)鎖writeLock:
writeLock是一個(gè)獨(dú)占鎖寫(xiě)鎖,當(dāng)一個(gè)線程獲得該鎖后,其他請(qǐng)求讀鎖或者寫(xiě)鎖的線程阻塞, 獲取成功后,會(huì)返回一個(gè)stamp(憑據(jù))變量來(lái)表示該鎖的版本,在釋放鎖時(shí)調(diào)用unlockWrite方法傳遞stamp參數(shù)。提供了非阻塞式獲取鎖tryWriteLock。
2. 悲觀讀鎖readLock:
readLock是一個(gè)共享讀鎖,在沒(méi)有線程獲取寫(xiě)鎖情況下,多個(gè)線程可以獲取該鎖。如果有寫(xiě)鎖獲取,那么其他線程請(qǐng)求讀鎖會(huì)被阻塞。悲觀讀鎖會(huì)認(rèn)為其他線程可能要對(duì)自己操作的數(shù)據(jù)進(jìn)行修改,所以需要先對(duì)數(shù)據(jù)進(jìn)行加鎖,這是在讀少寫(xiě)多的情況下考慮的。請(qǐng)求該鎖成功后會(huì)返回一個(gè)stamp值,在釋放鎖時(shí)調(diào)用unlockRead方法傳遞stamp參數(shù)。提供了非阻塞式獲取鎖方法tryWriteLock。
3. 樂(lè)觀讀鎖tryOptimisticRead:
tryOptimisticRead相對(duì)比悲觀讀鎖,在操作數(shù)據(jù)前并沒(méi)有通過(guò)CAS設(shè)置鎖的狀態(tài),如果沒(méi)有線程獲取寫(xiě)鎖,則返回一個(gè)非0的stamp變量,獲取該stamp后在操作數(shù)據(jù)前還需要調(diào)用validate方法來(lái)判斷期間是否有線程獲取了寫(xiě)鎖,如果是返回值為0則有線程獲取寫(xiě)鎖,如果不是0則可以使用stamp變量的鎖來(lái)操作數(shù)據(jù)。
由于tryOptimisticRead并沒(méi)有修改鎖狀態(tài),所以不需要釋放鎖。
這是讀多寫(xiě)少的情況下考慮的,不涉及CAS操作,所以效率較高,在保證數(shù)據(jù)一致性上需要復(fù)制一份要操作的變量到方法棧中,并且在操作數(shù)據(jù)時(shí)可能其他寫(xiě)線程已經(jīng)修改了數(shù)據(jù),而我們操作的是方法棧里面的數(shù)據(jù),也就是一個(gè)快照,所以最多返回的不是最新的數(shù)據(jù),但是一致性得到了保證。