自旋鎖:spinlock
是指嘗試獲取鎖的線程不會立即阻塞,而是采用循環的方式獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環耗用CPU

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class SpinLockTest {
/**
* 自旋鎖:
* 是指嘗試獲取鎖的線程不會立即阻塞,而是采用循環的方式獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環耗用CPU
* 而在一個多核的機器中,多個線程是可以並行執行的。如果當后面請求鎖的線程沒拿到鎖的時候,不掛起線程,而是繼續占用處理器的執行時間,
* 讓當前線程執行一個忙循環(自旋操作),
* 也就是不斷在盯着持有鎖的線程是否已經釋放鎖,那么這就是傳說中的自旋鎖了。
* @param args
*/
/**
* 1.6 版本后使用了自適應自旋鎖:
* 自旋次數通常由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態決定。如果線程【T1】自旋成功,自旋次數為17次,那么等到下一個線程【T2】自旋時,
* 也會默認認為【T2】自旋17次成功,
如果【T2】自旋了5次就成功了,那么此時這個自旋次數就會縮減到5次。
自適應自旋鎖隨着程序運行和性能監控信息,從而使得虛擬機可以預判出每個線程大約需要的自旋次數
* @param args
*/
public static void main(String[] args) {
SpinLockTest sl= new SpinLockTest();
// 給線程賦予AA名稱
new Thread(()->{
sl.myLock();
try {
// 休眠5 秒
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sl.unMyLock();
},"AA").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(()-> {
sl.myLock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sl.unMyLock();
},"BB").start();
}
// AtomicReference 原子方式更新對象引用 ,保證多線程下操作該對象進行更新時,避免出現臟讀,只要有一個線程改變 ,
//其他現場不會在改變該值
AtomicReference<Thread> atomicReference = new AtomicReference<>();
// null 表示鎖未被線程持有, atomicReference.compareAndSet(t,null); 線程的持有狀態改變為null
public void myLock() {
Thread t= Thread.currentThread();
System.out.println(t.currentThread().getName()+ "come in");
while (!atomicReference.compareAndSet(null, t)) {
}
}
public void unMyLock() {
Thread t= Thread.currentThread();
atomicReference.compareAndSet(t,null);
System.out.println(t.currentThread().getName()+ "invoked unMyLock() ");
}
}
