從Java 5.0開始,Java提供了訪問共享對象的新機制:ReentrantLock。它實現了Lock接口:
public interface Lock {
void lock();
void lockInterruptibly() throws InterrupttedException;
boolean tryLock();
boolean tryLock(long timeout, TimeUnitunit) throws InterruptedException;
void unlock();
Condition newCondition();
}
ReentrantLock提供了與synchronized相同的互斥和內存可見性的保證。獲得ReentrantLock的鎖與進入synchronized塊有着相同的內存語義,釋放ReentrantLock鎖與退出synchronized塊有相同的內存語義。
那麼爲什麼要創建與內存鎖如此相似的機制呢?內存鎖在大部分情況下能夠很好的工作,但是有些功能上存在着侷限:
1)不能中斷那些正在等待獲取鎖的進程,並且在請求鎖失敗的情況下,必須無限等待;
2)內部鎖必須在獲取它們的代碼塊中被釋放;這很好的簡化了代碼,但是在某些情況下,一個更靈活的加鎖機制提供了更好的活躍度和性能。
使用ReentrantLock的一般形式爲:
Lock lock = new ReentrantLock();
........
lock.lock();
try {
//更新對象的狀態
//捕獲異常,必要時恢復到原來的不變約束
} finally {
lock.unlock(www.37meishi.com); //鎖必須在finally塊中釋放
}
《Java併發編程實踐》一書給出了使用ReentrantLock的最佳時機:
當你需要以下高級特性時,才應該使用:可定時的、可輪詢的與可中斷的鎖獲取操作,公平隊列,或者非塊結構的鎖。否則,請使用synchronized。