10.Java鎖之自旋鎖

概念

自旋鎖(spinlock):是指嘗試獲取鎖的線程不會當即阻塞,而是採用循環的方式去嘗試獲取鎖。java

  • 以前學過的CAS,底層使用的就是自旋鎖,自旋就是屢次嘗試,屢次訪問,不會阻塞的狀態就是自旋。

優缺點

優勢:循環比較獲取直到成功,沒有相似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佔用完鎖,也出來了
相關文章
相關標籤/搜索