本文簡單介紹下自旋鎖的阻塞鎖,主要詳細介紹自旋鎖的概念、使用場景和簡易代碼實現。
概述
我們都知道CPU喚醒或者阻塞線程時,是有上下文切換的開銷,若臨界區的范圍不是很大,在多核處理器中使用自旋鎖是ok的。
自旋鎖:采用CAS的方法,不停的去嘗試獲取,直到獲取成功
缺點
若臨界區很耗時,使用自旋鎖隨着時間的推移會有很多的性能問題
優點
在一定程度上,自旋可以提供效率,JDK中的atomic采用了自旋鎖。
代碼示例
下文通過代碼去演示自旋鎖的實現,采用CAS,while循環去實現。如下所示。
package com.yang.lock;
import java.util.concurrent.atomic.AtomicReference;
/**
* 本實例演示下線程的自旋鎖的實現
*/
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自旋鎖獲取失敗,重新獲取中
