本文簡單介紹下自旋鎖的阻塞鎖,主要詳細介紹自旋鎖的概念、使用場景和簡易代碼實現。
概述
我們都知道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自旋鎖獲取失敗,重新獲取中