synchronized和ReentrantLock
Java的內置鎖synchronized和ReentrantLock有相同的內存語義。但內置鎖在功能上有不足,如不能中斷一個正在等待獲得鎖的線程,或者無法請求獲得一個鎖時無限等待下去。
相對於內置鎖 - 顯式鎖 ReentrantLock更加靈活,提供了可輪詢的,定時的,可中斷的的鎖操作,非塊結構的加鎖以及公平鎖/非公平鎖的選擇。
ReentrantLock實現Lock接口,使用時必須要在finally塊中釋放。
輪詢鎖與定時鎖
ReentrantLock通過tryLock方法提供可輪詢的與定時的鎖,可避免死鎖。
內置鎖通常通過一致的鎖順序避免死鎖。
可中斷的鎖獲取操作
ReentrantLock 的lockInterruptibly方法獲取鎖並能響應中斷。
定時的tryLock方法也可以獲取鎖並響應中斷。
非塊結構的加鎖
synchronized和ReentrantLock的性能比較
ReentrantLock性能在Java 5勝出很多,在Java 6略勝出。
公平性
默認的ReentrantLock 和 內置鎖一樣不會提供公平性保證。
ReentrantLock有一個帶boolean類型參數的構造器,它允許您創建一個公平(fair)鎖,或不公平(unfair)鎖。公平鎖使線程按照請求鎖的順序依次獲得鎖;而不公平鎖則允許討價還價,在這種情況下,線程有時可以比先請求鎖的其他線程先得到鎖。
在大多數情況下,非公平鎖的性能高於公平鎖。
當持有鎖的時間比較長,或請求鎖的平均時間間隔較長,那麼應該使用公平鎖。
如何選擇synchronized和ReentrantLock
優先選擇內置鎖,內置鎖不能滿足時用ReentrantLock.
讀寫鎖
synchronized和ReentrantLock是標準的互斥鎖,每次最多隻有一個線程能持有鎖。互斥是一種保守的加鎖策略,它避免了寫-寫和讀-寫衝突,但也避免了讀-讀衝突,造成不必要的併發。
大多數的訪問操作可能是讀操作,應該允許多個線程同時訪問來提高程序的性能。Java提供了讀寫鎖(ReadWriteLock)機制。
什麼情況下使用讀寫鎖?
一個資源可以被多個讀操作訪問,或者被一個寫操作訪問,但兩者不能同時進行。
示例