ReentrantLock可重入鎖、公平鎖非公平鎖區(qū)別與實(shí)現(xiàn)原理
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
ReentrantLock是lock接口的一個(gè)實(shí)現(xiàn)類,里面實(shí)現(xiàn)了可重入鎖和公平鎖非公平鎖
ReentrantLock公平鎖和不公平鎖實(shí)現(xiàn)原理
公平鎖會(huì)獲取鎖時(shí)會(huì)判斷阻塞隊(duì)列里是否有線程再等待,若有獲取鎖就會(huì)失敗,并且會(huì)加入阻塞隊(duì)列
非公平鎖獲取鎖時(shí)不會(huì)判斷阻塞隊(duì)列是否有線程再等待,所以對(duì)于已經(jīng)在等待的線程來(lái)說(shuō)是不公平的,但如果是因?yàn)槠渌驔](méi)有競(jìng)爭(zhēng)到鎖,它也會(huì)加入阻塞隊(duì)列
進(jìn)入阻塞隊(duì)列的線程,競(jìng)爭(zhēng)鎖時(shí)都是公平的,應(yīng)為隊(duì)列為先進(jìn)先出(FIFO)
默認(rèn)實(shí)現(xiàn)的是非公平鎖
public?ReentrantLock()?{
????//非公平鎖
????sync?=?new?NonfairSync();
}
還提供了另外一種方式,可傳入一個(gè)boolean值,true時(shí)為公平鎖,false時(shí)為非公平鎖
//公平鎖
public?ReentrantLock(boolean?fair)?{
????sync?=?fair???new?FairSync()?:?new?NonfairSync();
}
非公平鎖
非公平鎖獲取鎖nonfairTryAcquire方法,對(duì)鎖狀態(tài)進(jìn)行了判斷,并沒(méi)有把鎖加入同步隊(duì)列中
????static?final?class?NonfairSync?extends?Sync?{
????????private?static?final?long?serialVersionUID?=?7316153563782823691L;
????????final?void?lock()?{
????????????//比較當(dāng)前狀態(tài)?如果持有者是當(dāng)前線程
????????????if?(compareAndSetState(0,?1))
????????????????setExclusiveOwnerThread(Thread.currentThread());
????????????else
????????????????//如果不是?嘗試獲取鎖
????????????????acquire(1);
????????}
????????protected?final?boolean?tryAcquire(int?acquires)?{
????????????//獲取鎖
????????????return?nonfairTryAcquire(acquires);
????????}
????}
final?boolean?nonfairTryAcquire(int?acquires)?{
????????????final?Thread?current?=?Thread.currentThread();
????????????int?c?=?getState();
????????????//判斷當(dāng)前對(duì)象是否被持有
????????????if?(c?==?0)?{
????????????????//沒(méi)有持有就直接改變狀態(tài)持有鎖
????????????????if?(compareAndSetState(0,?acquires))?{
????????????????????setExclusiveOwnerThread(current);
????????????????????return?true;
????????????????}
????????????}
?????????//若被持有?判斷鎖是否是當(dāng)前線程??也是可重入鎖的關(guān)鍵代碼
????????????else?if?(current?==?getExclusiveOwnerThread())?{
????????????????int?nextc?=?c?+?acquires;
????????????????if?(nextc?0)?//?overflow
????????????????????throw?new?Error("Maximum?lock?count?exceeded");
????????????????setState(nextc);
????????????????return?true;
????????????}
????????????return?false;
????????}
公平鎖
代碼和nonfairTryAcquire唯一的不同在于增加了hasQueuedPredecessors方法的判斷
static?final?class?FairSync?extends?Sync?{
????????private?static?final?long?serialVersionUID?=?-3000897897090466540L;
???????protected?final?boolean?tryAcquire(int?acquires)?{
???????????//獲取當(dāng)前線程
????????????final?Thread?current?=?Thread.currentThread();
????????????int?c?=?getState();
????????????//判斷當(dāng)前對(duì)象是否被持有
????????????if?(c?==?0)?{
????????????????//如果等待隊(duì)列為空?并且使用CAS獲取鎖成功???否則返回false然后從隊(duì)列中獲取節(jié)點(diǎn)
????????????????if?(!hasQueuedPredecessors()?&&compareAndSetState(0,?acquires))?{
????????????????????//把當(dāng)前線程持有
????????????????????setExclusiveOwnerThread(current);
????????????????????return?true;
????????????????}
????????????}
???????????//若被持有?判斷鎖是否是當(dāng)前線程??可重入鎖的關(guān)鍵代碼
????????????else?if?(current?==?getExclusiveOwnerThread())?{
????????????????//計(jì)數(shù)加1?返回
????????????????int?nextc?=?c?+?acquires;
????????????????if?(nextc?0)
????????????????????throw?new?Error("Maximum?lock?count?exceeded");
????????????????setState(nextc);
????????????????return?true;
????????????}
????????????//不是當(dāng)前線程持有?執(zhí)行
????????????return?false;
????????}
????}
acquire()獲取鎖
????public?final?void?acquire(int?arg)?{
????????//如果當(dāng)前線程嘗試獲取鎖失敗并且?加入把當(dāng)前線程加入了等待隊(duì)列?
????????if?(!tryAcquire(arg)?&&acquireQueued(addWaiter(Node.EXCLUSIVE),?arg))
????????????//先中斷當(dāng)前線程
????????????selfInterrupt();
????}
關(guān)鍵代碼
就是tryAcquire方法中hasQueuedPredecessors判斷隊(duì)列是否有其他節(jié)點(diǎn)
public?final?boolean?hasQueuedPredecessors()?{
????Node?t?=?tail;?//?Read?fields?in?reverse?initialization?order
????Node?h?=?head;
????Node?s;
????return?h?!=?t?&&
????????((s?=?h.next)?==?null?||?s.thread?!=?Thread.currentThread());
}
可重入性實(shí)現(xiàn)原理
在線程獲取鎖的時(shí)候,如果已經(jīng)獲取鎖的線程是當(dāng)前線程的話則直接再次獲取成功
由于鎖會(huì)被獲取n次,那么只有鎖在被釋放同樣的n次之后,該鎖才算是完全釋放成功
1、獲取鎖方法
?protected?final?boolean?tryAcquire(int?acquires)?{
???????????//獲取當(dāng)前線程
????????????final?Thread?current?=?Thread.currentThread();
????????????int?c?=?getState();
????????????//判斷當(dāng)前對(duì)象是否被持有
????????????if?(c?==?0)?{
??????????????//...略
????????????}
???????????//若被持有?判斷鎖是否是當(dāng)前線程??可重入鎖的關(guān)鍵代碼
????????????else?if?(current?==?getExclusiveOwnerThread())?{
????????????????//計(jì)數(shù)加1?返回
????????????????int?nextc?=?c?+?acquires;
????????????????if?(nextc?0)
????????????????????throw?new?Error("Maximum?lock?count?exceeded");
????????????????setState(nextc);
????????????????return?true;
????????????}
????????????//不是當(dāng)前線程持有?執(zhí)行
????????????return?false;
????????}
每次如果獲取到的都是當(dāng)前線程這里都會(huì)計(jì)數(shù)加1
釋放鎖
protected?final?boolean?tryRelease(int?releases)?{
????//每次釋放都減1
????int?c?=?getState()?-?releases;
????if?(Thread.currentThread()?!=?getExclusiveOwnerThread())
????????throw?new?IllegalMonitorStateException();
????boolean?free?=?false;
????//等于0才釋放鎖成功
????if?(c?==?0)?{
????????free?=?true;
????????setExclusiveOwnerThread(null);
????}
????setState(c);
????return?free;
}
如果鎖被獲取n次,也要釋放了n次,只有完全釋放才會(huì)返回false
? 作者?|??cg-ww
來(lái)源 |??cnblogs.com/cg-ww/p/15422013.html

