自旋鎖(spinlock):是指當(dāng)一個(gè)線程在獲取鎖的時(shí)候雁竞,如果鎖已經(jīng)被其它線程獲取钦椭,那么該線程將循環(huán)等待,然后不斷的判斷鎖是否能夠被成功獲取,直到獲取到鎖才會(huì)退出循環(huán)彪腔。
自旋鎖的一種經(jīng)典實(shí)現(xiàn):
import java.util.concurrent.atomic.AtomicReference;
public class UnReentrantLock {
private volatile AtomicReference<Thread> owner = new AtomicReference<Thread>();
public void lock() {
Thread current = Thread.currentThread();
//這句是很經(jīng)典的“自旋”語(yǔ)法侥锦,AtomicInteger中也有
for (;;) {
if (owner.compareAndSet(null, current)) {
return;
}
}
}
public void unlock() {
Thread current = Thread.currentThread();
owner.compareAndSet(current, null); // 只試一次
}
}
自旋鎖的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):自旋鎖不會(huì)使線程狀態(tài)發(fā)生切換,一直處于用戶態(tài)德挣,即線程一直都是active的恭垦;不會(huì)使線程進(jìn)入阻塞狀態(tài),減少了不必要的上下文切換盲厌,執(zhí)行速度快署照。非自旋鎖在獲取不到鎖的時(shí)候會(huì)進(jìn)入阻塞狀態(tài),從而進(jìn)入內(nèi)核態(tài)吗浩,當(dāng)獲取到鎖的時(shí)候需要從內(nèi)核態(tài)恢復(fù)建芙,需要線程上下文切換。 (線程被阻塞后便進(jìn)入內(nèi)核(Linux)調(diào)度狀態(tài)懂扼,這個(gè)會(huì)導(dǎo)致系統(tǒng)在用戶態(tài)與內(nèi)核態(tài)之間來(lái)回切換禁荸,嚴(yán)重影響鎖的性能)
缺點(diǎn):如果某個(gè)線程持有鎖的時(shí)間過(guò)長(zhǎng),就會(huì)導(dǎo)致其它等待獲取鎖的線程進(jìn)入循環(huán)等待阀湿,消耗CPU赶熟。使用不當(dāng)會(huì)造成CPU使用率極高。
這把自旋鎖是不公平的陷嘴、不可重入的映砖。怎樣實(shí)現(xiàn)一把可重入的自旋鎖?
class ReentrantSpinLock {
private volatile AtomicReference<Thread> cas = new AtomicReference<Thread>();
private volatile int count;
public void lock() {
Thread current = Thread.currentThread();
if (current == cas.get()) {
count++;
return;
}
while (!cas.compareAndSet(null, current)) {
// DO nothing
}
}
public void unlock() {
Thread cur = Thread.currentThread();
// 只有獲得了鎖灾挨,才能執(zhí)行unlock
if (cur == cas.get()) {
if (count > 0) {
count--;
} else {
cas.compareAndSet(cur, null);
}
}
}
}
注意這兩段代碼中volatile的使用邑退。
鎖的狀態(tài):
1.無(wú)鎖狀態(tài)
2.偏向鎖狀態(tài)
3.輕量級(jí)鎖狀態(tài)
4.重量級(jí)鎖狀態(tài)
鎖的狀態(tài)是通過(guò)對(duì)象監(jiān)視器在對(duì)象頭中的字段來(lái)表明的。
四種狀態(tài)會(huì)隨著競(jìng)爭(zhēng)的情況逐漸升級(jí)劳澄,而且是不可逆的過(guò)程地技,即不可降級(jí)。
這四種狀態(tài)都不是Java語(yǔ)言中的鎖秒拔,而是Jvm為了提高鎖的獲取與釋放效率而做的優(yōu)化(使用synchronized時(shí))莫矗。
偏向鎖
偏向鎖是指一段同步代碼一直被一個(gè)線程所訪問(wèn),那么該線程會(huì)自動(dòng)獲取鎖砂缩。降低獲取鎖的代價(jià)作谚。
輕量級(jí)
輕量級(jí)鎖是指當(dāng)鎖是偏向鎖的時(shí)候,被另一個(gè)線程所訪問(wèn)梯轻,偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖食磕,其他線程會(huì)通過(guò)自旋的形式嘗試獲取鎖,不會(huì)阻塞喳挑,提高性能彬伦。
重量級(jí)鎖
重量級(jí)鎖是指當(dāng)鎖為輕量級(jí)鎖的時(shí)候滔悉,另一個(gè)線程雖然是自旋,但自旋不會(huì)一直持續(xù)下去单绑,當(dāng)自旋一定次數(shù)的時(shí)候回官,還沒(méi)有獲取到鎖,就會(huì)進(jìn)入阻塞搂橙,該鎖膨脹為重量級(jí)鎖歉提。重量級(jí)鎖會(huì)讓其他申請(qǐng)的線程進(jìn)入阻塞,性能降低区转。