阻塞或者喚醒一個Java線程須要操做系統切換CPU 狀態來完成,這種狀態轉換 須要耗費處理器時間
若是同步代碼塊到代碼過於簡單,狀態轉換到時間有kennel比用戶執行代碼到時間還長
在許多場景下,同步資源到鎖定時間短,爲了這小段時間切換線程,線程的掛起和恢復可能會讓系統得不償失,服務器
這裏是爲了當前線程「 稍等一下」, 咱們須要讓當前線程進行自旋 ,若是自旋完成後前面鎖定同步資源的線程以及釋放了鎖,那麼當前線程就不必阻塞,而是直接獲取同步資源,從而避免線程的開銷
阻塞鎖和自旋鎖相反,阻塞鎖若是沒有拿到鎖,就會直接阻塞,知道被喚醒併發
阻塞鎖是指當線程嘗試獲取鎖失敗時,線程進入阻塞狀態,直到接收信號後被喚醒.(線程的狀態包括新建、就緒、運行、阻塞及死亡)在JAVA中,可以喚醒阻塞線程的操做包括Object.notify, Object.notifyAll, Condition.signal, LockSupport.unpark(JUC中引入)框架
在 jdk 1.5 及以上併發框架 Java.util.concurrent 的 atomic 下 都是自旋鎖實現的ide
AtomicInteger 的實現 :自旋鎖的世勳啊原理是CAS AtomicInteger 中是調用底層unsafe 進行自增操做的源碼中的 do-while 循環就是一個自旋操做,若是修改過程當中一踏線程競爭致使修改失敗,就在while 死循環,直至成功源碼分析
package com.dimple.test;
/**
* 本實例演示下線程的自旋鎖的實現
*/
public class SpinLockDemo {
private static AtomicReference<Thread> atomicReference=new AtomicReference<>();
public void lock(){
Thread thread=Thread.currentThread();
while(!atomicReference.compareAndSet(null,thread)){
System.out.println(thread.getName()+"自旋鎖獲取失敗,從新獲取中");
}
}
public void unlock(){
Thread thread=Thread.currentThread();
atomicReference.compareAndSet(thread,null);
}
public static void main(String[] args) {
SpinLockDemo spinLockDemo=new SpinLockDemo();
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"嘗試獲取自旋鎖");
spinLockDemo.lock();
System.out.println(Thread.currentThread().getName()+"獲取自旋鎖成功");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLockDemo.unlock();
System.out.println(Thread.currentThread().getName()+"釋放自旋鎖");
}).start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"嘗試獲取自旋鎖");
spinLockDemo.lock();
System.out.println(Thread.currentThread().getName()+"獲取自旋鎖成功");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLockDemo.unlock();
System.out.println(Thread.currentThread().getName()+"釋放自旋鎖");
}).start();
}
}
Thread-0嘗試獲取自旋鎖
Thread-0獲取自旋鎖成功
Thread-1嘗試獲取自旋鎖
Thread-1自旋鎖獲取失敗,從新獲取中
Thread-1自旋鎖獲取失敗,從新獲取中
Thread-1自旋鎖獲取失敗,從新獲取中
Thread-1自旋鎖獲取失敗,從新獲取中
咱們打開 AtomicInteger 源碼看一下,這裏是個 do while 循環ui
自旋鎖通常用於多核服務器,在併發度不是特別搞的狀況下,比阻塞鎖效率高, 另外,自旋鎖適用於臨界區較小的狀況,不然若是臨界區很大,(線程一旦拿到鎖,不少以後纔會釋放),那也是不適合的atom