1. 簡(jiǎn)介
ReentrantLock與synchronized關(guān)鍵字一樣是可重入的獨(dú)占鎖,不過(guò)ReentrantLock提供比synchronized關(guān)鍵字更加靈活的獲取鎖和釋放鎖操作,并且支持等待多個(gè)條件,但ReentrantLock必須手動(dòng)釋放鎖,否則很有可能造成死鎖。在JDK6之后,synchronized加入了偏向鎖、輕量級(jí)鎖、自適應(yīng)自旋、鎖粗化、鎖消除多種優(yōu)化措施使它的性能提高了很多,通常情況下表現(xiàn)一般比ReentrantLock好,所以在能使用synchronized功能完成的操作時(shí),盡量不要用ReentrantLock。ReentrantLock中大部分方法是間接調(diào)用了AbstractQueuedSynchronizer的方法,所以要想進(jìn)一步探究其實(shí)現(xiàn)可以看看上一篇文章AbstractQueuedSynchronizer源碼解析
2. 實(shí)現(xiàn)
繼承關(guān)系
ReentrantLock實(shí)現(xiàn)了Lock接口
public class ReentrantLock implements Lock, java.io.Serializable {}
Lock接口提供了鎖最基本的幾個(gè)方法,實(shí)現(xiàn)該接口的類(lèi)都重寫(xiě)了這些方法
public interface Lock {
// 阻塞獲取鎖
void lock();
// 阻塞獲取鎖,可響應(yīng)中斷拋出異常
void lockInterruptibly() throws InterruptedException;
// 嘗試獲取鎖
boolean tryLock();
// 嘗試在指定時(shí)間內(nèi)獲取鎖,獲取不到則阻塞直到獲取到鎖返回true或超時(shí)返回false
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 釋放鎖
void unlock();
// 創(chuàng)建一個(gè)等待條件,獲取鎖的線程可以等待條件
Condition newCondition();
}
屬性
ReentrantLock中最重要的屬性就是sync,sync是個(gè)實(shí)現(xiàn)抽象隊(duì)列同步器AbstractQueuedSynchronizer抽象方法tryAcquire和tryRelease的類(lèi)的對(duì)象,其中tryAcquire方法決定了是否公平、重入的特性,而tryRelease方法對(duì)公平與非公平重入鎖都適用。ReentrantLock中方法的實(shí)現(xiàn)基本都是調(diào)用sync的方法。
private final Sync sync;
Sync
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
// 添加抽象方法lock
abstract void lock();
// 添加非公平獲取嘗試同步狀態(tài)的方法,該方法體現(xiàn)非公平性與重入特性
final boolean nonfairTryAcquire(int acquires) {
// 獲取當(dāng)前線程
final Thread current = Thread.currentThread();
// 獲取當(dāng)前同步狀態(tài)
int c = getState();
// 如果沒(méi)有線程獲取同步狀態(tài)
if (c == 0) {
// 使用CAS方法獲取同步狀態(tài),這里體現(xiàn)非公平性,因?yàn)闆](méi)有判斷等待隊(duì)列里是否有其他線程在等待獲取同步狀態(tài)
if (compareAndSetState(0, acquires)) {
// 獲取成功則設(shè)置獨(dú)占線程
setExclusiveOwnerThread(current);
return true;
}
} // 否則當(dāng)前線程已經(jīng)獲取過(guò)同步狀態(tài)
else if (current == getExclusiveOwnerThread()) {
// 直接在原基礎(chǔ)狀態(tài)值加上acquires,體現(xiàn)重入性
int nextc = c + acquires;
// 如果nextc小于0表示線程獲取鎖的次數(shù)已經(jīng)超過(guò)最大值
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 設(shè)置新的同步狀態(tài)
setState(nextc);
return true;
}
return false;
}
// 重寫(xiě)tryRelease方法,對(duì)應(yīng)公平與非公平鎖都適用,體現(xiàn)重入性
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
// 判斷當(dāng)前線程是否獨(dú)占鎖
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
// 創(chuàng)建等待條件
final ConditionObject newCondition() {
return new ConditionObject();
}
// 獲取獨(dú)占鎖的線程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
// 獲取當(dāng)前線程加鎖次數(shù)
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
// 是否已加鎖
final boolean isLocked() {
return getState() != 0;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
### NonfairSync
// 非公平鎖
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
// 如果當(dāng)前線程能直接獲取同步狀態(tài),則設(shè)置當(dāng)前線程為獨(dú)占線程
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else // 否則再調(diào)用acquire獲取同步狀態(tài)
acquire(1);
}
// 重寫(xiě)tryAcquire方法,調(diào)用nonfairTryAcquire方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
FairSync
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
// 重寫(xiě)tryAcquire方法,該方法體現(xiàn)公平性與重入特性
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 如果還沒(méi)有線程獲取同步狀態(tài)
if (c == 0) {
// 判斷等待隊(duì)列中是否有后繼線程,沒(méi)有再使用CAS方法獲取同步狀態(tài),
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
// 獲取成功設(shè)置當(dāng)前線程為獨(dú)占線程
setExclusiveOwnerThread(current);
return true;
}
} // 否則當(dāng)前線程已經(jīng)獲取過(guò)同步狀態(tài)
else if (current == getExclusiveOwnerThread()) {
// 直接在原基礎(chǔ)狀態(tài)值加上acquires,體現(xiàn)重入性
int nextc = c + acquires;
// 如果nextc小于0表示線程獲取鎖的次數(shù)已經(jīng)超過(guò)最大值
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 設(shè)置新的同步狀態(tài)
setState(nextc);
return true;
}
return false;
}
}
構(gòu)造函數(shù)
// 默認(rèn)創(chuàng)建非公平鎖
public ReentrantLock() {
sync = new NonfairSync();
}
// 根據(jù)指定參數(shù)創(chuàng)建公平或非公平鎖
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
獲取鎖方法
以下獲取鎖的方法都是調(diào)用Sync類(lèi)的方法或或從抽象隊(duì)列同步器繼承的方法
// 阻塞獲取鎖
public void lock() {
sync.lock();
}
// 中斷獲取鎖
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
// 嘗試獲取鎖
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
// 超時(shí)獲取鎖
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
釋放鎖方法
public void unlock() {
sync.release(1);
}