【CAP】CAS和自旋鎖

自旋鎖可以看成是不斷自動重試的樂觀鎖,也會有樂觀鎖的ABA問題。

自旋鎖的實現基礎是CAS功能。

什么是自旋鎖?

自旋鎖(spinlock):是指當一個線程在獲取鎖的時候,如果鎖已經被其它線程獲取,那么該線程將循環等待,然后不斷的判斷鎖是否能夠被成功獲取,直到獲取到鎖才會退出循環。

獲取鎖的線程一直處于活躍狀態,但是并沒有執行任何有效的任務,使用這種鎖會造成busy-waiting。

它是為實現保護共享資源而提出一種鎖機制。其實,自旋鎖與互斥鎖比較類似,它們都是為了解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。

兩者在調度機制上略有不同。對于互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖,”自旋”一詞就是因此而得名。

什么是CAS

CAS(Compare-and-Swap),即比較并替換,是一種實現并發算法時常用到的技術,Java并發包中的很多類都使用了CAS技術。

這里以AtomicInteger說明一下

1
2
3
4
5
6
7
8
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}

加1就是先獲取當前值,加1,設置時先對比當前值是不是內存中的值,如果是設置新值。

內存對比是通過本地方法實現的,需要操作系統的支持。

如果成功就可以退出循環,否則一直嘗試。

用AtomicReference實現自旋鎖

自旋鎖就是線程調用lock()后,其他線程再調用lock()會卡住,等待鎖的釋放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SpinLock {
private AtomicReference<Thread> lock = new AtomicReference<Thread>();
public void lock() {
Thread current = Thread.currentThread();
// 利用CAS
while (!lock.compareAndSet(null, current)) {
// DO nothing
}
}
public void unlock() {
Thread current = Thread.currentThread();
lock.compareAndSet(current, null);
}
}

可以看出,第一個線程調用lock()時lock沒有set過值,對象是null,第二個線程在調用時已經set過值,所以會一直循環。

只有當第一個線程unlock()之后第二個循環才能結束。

体彩25选5走势图