當多線程共享一個資源變量的時候,需要對線程加以控制,以保證線程是安全的,共享的資源被有效的使用。
內置鎖(監視鎖)
synchronized作用域代碼塊上,是一種內存可見的內置鎖。
synchronized是一種可重入鎖:同一個線程可以獲得它自己持有的鎖。
synchronized(x1) {
code1;
synchronized(x2) {
code2;
}
}
顯示鎖
Lock
ReentrantLock的作用相當於一種內置鎖,但不是一種替換內置加鎖的方法,而是當內置加鎖機制不適用時,作爲一種可選擇的高級功能。ReentrantLock也提供了可重入的加鎖語義,與synchronized相比,它還爲處理鎖的不可用性問題提供了更高級的靈活性。
Lock lock = new ReentrantLock ();
...
lock.lock()
try {
// 更新對象狀態
// 捕獲異常,並在必要時恢復不變性條件
}finally {
lock.unlock();
}
鎖輪詢與定時鎖
可定時的與可輪詢的鎖獲取模式是由tryLock方法實現的,與無條件的鎖獲取模式相比,它具有更完善的錯誤恢復機制。
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
可中斷的鎖獲取操作
非塊結構的加鎖
公平性
在公平的鎖上,線程將按照它們發出請求的順序來獲取鎖,但在非公平的鎖上,則允許“插隊”。
/**
* 默認獲取的是非公平鎖
*/
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
讀寫鎖
讀寫鎖實現類ReentrantReadWriteLock繼承於ReadWriteLock接口
在讀 - 寫鎖實現的加鎖策略中,允許多個讀操作同時進行,但每次只允許一個寫操作。
synchronized與lock鎖的選擇
在一些內置鎖無法滿足需要的情況下,ReentrantLock可以作爲一種高級工具。當需要一些高級功能時才應該使用ReentrantLock,這些功能包括:可定時的、可輪詢的與可中斷的鎖獲取操作,公平隊列,以及非塊結構的鎖。否則,還是應該優先使用synchronized。