自旋鎖(spinlock):是指嘗試獲取鎖的線程不會當即阻塞,而是採用循環的方式去嘗試獲取鎖。java
優勢:循環比較獲取直到成功,沒有相似wait的阻塞。還能減小線程上下文切換的消耗測試
缺點:當不斷自旋的線程愈來愈多的時候,會由於執行while循環不斷的消耗CPU資源atom
自旋的本質就是CAS方法和while循環線程
public class SpinLockDemo { // 原子引用線程 AtomicReference<Thread> atomicReference = new AtomicReference<>(); public void myLock() { Thread thread = Thread.currentThread(); // 返回對當前正在執行的線程對象的引用 System.out.println(Thread.currentThread().getName() + "進來了"); /* 首個線程進來,發現atomicReference是null,就變爲這個線程。而後取反變爲false,跳出循環等待。 若是發現衛生間裏面還有人,就一直循環一直等,直到衛生間裏面沒人。 */ while (!atomicReference.compareAndSet(null, thread)) { //沒跳出就一直循環 } } public void myUnlock() { Thread thread = Thread.currentThread(); // 我出去要解鎖,而後變爲null給下一我的用 atomicReference.compareAndSet(thread, null); System.out.println(Thread.currentThread().getName() + "調用myUnlock方法"); }
測試code
public static void main(String[] args) throws InterruptedException { SpinLockDemo spinLockDemo = new SpinLockDemo(); // 我A線程進去佔用這把鎖,而後霸佔5s new Thread(() -> { spinLockDemo.myLock(); TimeUnit.SECONDS.sleep(5); spinLockDemo.myUnlock(); }, "線程A").start(); // 主線程main暫停1s,保證A線程先啓動 TimeUnit.SECONDS.sleep(1); // 我B線程再進去循環等待這把鎖 new Thread(() -> { spinLockDemo.myLock(); spinLockDemo.myUnlock(); }, "線程B").start(); }
運行結果對象
線程A進來了 //A進來了,A要佔用5s 線程B進來了 //B也進來了,發現衛生間有人,循環等待A出來 線程A調用myUnlock方法 //A出來了 線程B調用myUnlock方法 //B佔用完鎖,也出來了