1. 程式人生 > >Java併發框架——AQS阻塞佇列管理(一)——自旋鎖

Java併發框架——AQS阻塞佇列管理(一)——自旋鎖

我們知道一個執行緒在嘗試獲取鎖失敗後將被阻塞並加入等待佇列中,它是一個怎樣的佇列?又是如何管理此佇列?這節聊聊CHL Node FIFO佇列。
 在談到CHL Node FIFO佇列之前,我們先分析這種佇列的幾個要素。首先要了解的是自旋鎖,所謂自旋鎖即是某一執行緒去嘗試獲取某個鎖時,如果該鎖已經被其他執行緒佔用的話,此執行緒將不斷迴圈檢查該鎖是否被釋放,而不是讓此執行緒掛起或睡眠。它屬於為了保證共享資源而提出的一種鎖機制,與互斥鎖類似,保證了公共資源在任意時刻最多隻能由一條執行緒獲取使用,不同的是互斥鎖在獲取鎖失敗後將進入睡眠或阻塞狀態。下面利用程式碼實現一個簡單的自旋鎖,
public class SpinLock {
private static Unsafe unsafe = null;
private static final long valueOffset;
private volatile int value = 0;
static {
try {
unsafe=getUnsafeInstance();
valueOffset = unsafe.objectFieldOffset(SpinLock.class
.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private static Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
public void lock() {
for (;;) {

            int newV = value + 1;

            if(newV==1)

                if (unsafe.compareAndSwapInt(this, valueOffset, 0, newV)){
                return ;
                }
        }
}
public void unlock() {
unsafe.compareAndSwapInt(this, valueOffset, 1, 0);
}
}
這是一個很簡單的自旋鎖,主要看加粗加紅的兩個方法lock和unlock,Unsafe僅僅是為操作提供了硬體級別的原子CAS操作,暫時忽略此類,只要知道它的作用即可,我們將在後面的“原子性如何保證”小節中對此進行更加深入的闡述。對於lock方法,假如有若干執行緒競爭,能成功通過CAS操作修改value值為newV的執行緒即是成功獲取鎖的執行緒,將直接通過,而其他的執行緒則不斷在迴圈檢測value值是否又改回0,而將value改為0的操作就是獲取鎖的執行緒執行完後對該鎖進行釋放,通過unlock方法釋放鎖,釋放後若干執行緒又對該鎖競爭。如此一來,沒獲取的鎖也不會被掛起或阻塞,而是不斷迴圈檢查狀態。圖2-5-9-3可加深自旋鎖的理解,五條執行緒輪詢value變數,t1獲取成功後將value置為1,此狀態時其他執行緒無法競爭鎖,t1使用完鎖後將value置為0,剩下的執行緒繼續競爭鎖,以此類推。這樣就保證了某個區域塊的執行緒安全性。
 
圖2-5-9-3 自旋鎖

自旋鎖適用於鎖佔用時間短,即鎖保護臨界區很小的情景,同時它需要硬體級別操作,也要保證各快取資料的一致性,另外,無法保證公平性,不保證先到先獲得,可能造成執行緒飢餓。在多處理器機器上,每個執行緒對應的處理器都對同一個變數進行讀寫,而每次讀寫操作都將要同步每個處理器快取,導致系統性能嚴重下降。

點選訂購作者書籍《Tomcat核心設計剖析》

相關推薦

Java併發框架——AQS阻塞佇列管理——

我們知道一個執行緒在嘗試獲取鎖失敗後將被阻塞並加入等待佇列中,它是一個怎樣的佇列?又是如何管理此佇列?這節聊聊CHL Node FIFO佇列。 在談到CHL Node FIFO佇列之前,我們先分析這種佇列的幾個要素。首先要了解的是自旋鎖,所謂自旋鎖即是某一執行緒去嘗試獲取某個

Java併發框架——AQS阻塞佇列管理——優化

看Craig, Landin, and Hagersten發明的CLH鎖如何優化同步帶來的花銷,其核心思想是:通過一定手段將所有執行緒對某一共享變數輪詢競爭轉化為一個執行緒佇列且佇列中的執行緒各自輪詢自己的本地變數。這個轉化過程由兩個要點,一是構建怎樣的佇列&如何構建

java併發機制的底層實現原理:volatile深入分析

     java程式碼最終會被類載入器載入到JVM中,然後轉化為彙編指令在CPU上執行。java中所使用的併發機制依賴於JVM的實現和CPU的指令。 1.volatile的應用 volatile是一個輕量級的synchronize,它保證了共享變數的可見性,確保了所有執

Java併發程式設計的藝術——讀書筆記 併發程式設計的挑戰

第一章 併發程式設計的挑戰 因為最近找工作,準備筆試/面試,開始嘗試閱讀這本書,我不常寫部落格,距上一次寫已經過去大概一年時間了,連CSDN密碼都忘了/衰,所以這次新開一個賬號重新開始,希望我能堅持下去。 第一章沒什麼內容,我認為其目的主要是給出足夠多的閱讀這本書的理

Java併發之synchronized關鍵字深度解析

前言         近期研讀路神之絕世武學,徜徉於浩瀚無垠知識之海洋,偶有攫取吉光片羽,惶恐未領略其精髓即隱入歲月深處,遂急忙記錄一二,順備來日吹cow之談資。本小系列為併發之親兒子-獨臂狂俠synchronized專場。 一、使用場景     &

Java併發(十八阻塞佇列BlockingQueue BlockingQueue(阻塞佇列)詳解 二叉堆()之 圖文解析 和 C語言的實現 多執行緒程式設計:阻塞併發佇列的使用總結 Java併發程式設計:阻塞佇列 java阻塞佇列 BlockingQueue(阻塞佇列)詳解

阻塞佇列(BlockingQueue)是一個支援兩個附加操作的佇列。 這兩個附加的操作是:在佇列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。 阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇列裡拿元素的執行緒。阻塞佇列就是生產者

Java併發6:阻塞佇列,Fork/Join框架

阻塞佇列 阻塞佇列是一個支援兩個附加操作的佇列。這兩個附加的操作支援阻塞的插入和移除方法: 支援阻塞的插入方法:佇列滿時,佇列會阻塞插入元素的執行緒,直到佇列不滿 支援阻塞的移除方法:佇列空時,獲取元素的執行緒會等待佇列變為非空 阻塞佇列常用於生產者消費者的場景。其中生產者是向佇列新增元素

深入理解Java併發框架AQS系列:獨佔Exclusive Lock

[深入理解Java併發框架AQS系列(一):執行緒](https://www.cnblogs.com/xijiu/p/14396061.html) [深入理解Java併發框架AQS系列(二):AQS框架簡介及鎖概念](https://www.cnblogs.com/xijiu/p/14522224.html)

JAVA併發程式設計:阻塞佇列-ArrayBlockingQueue

生活 有很多的不快樂,其實是源自不滿足,而不滿足,很多時候是源自於心不定,而心不定則是因為不清楚究竟自己要什麼,不清楚要什麼的結果就是什麼都想要,結果什麼都沒得到。 生產者消費者模式 生產者和消費者問題是執行緒模型中一個經典問題: 生產者和消費者在同一個時間段內共用一塊記憶體區域

JAVA併發程式設計:阻塞佇列-DelayQueue

生活 如果第一次你沒有成功,那麼稱之為1.0版,繼續加油。 DelayQueue的成員組成 今天來學習延時佇列,這個玩意兒也是非常重要,在定時器上有用到。 首先簡單瞭解下,延時佇列就是讓指定的資料再指定的時候以後出隊,也就是按照時間排序,因此它的核心確實是使用了昨天看的優先佇列。

Java併發程式設計 之 阻塞佇列和CountDownLatch

前幾天看到一個面試題目:有一個長度為2000的字串,開三個執行緒去判斷字串中”u51”的個數。 當時看到這個題目的時候,對併發程式設計是沒有什麼經驗的,在實際專案多執行緒的應用也只有一兩次。最近在惡補《Java併發程式設計的藝術》,對這個題目就有了解題的思路了。在這裡記錄一下對該題的

12-Java併發程式設計:阻塞佇列

Java併發程式設計:阻塞佇列   在前面幾篇文章中,我們討論了同步容器(Hashtable、Vector),也討論了併發容器(ConcurrentHashMap、CopyOnWriteArrayList),這些工具都為我們編寫多執行緒程式提供了很大的方便。今天我們來討

java併發-特大疑問-阻塞佇列(BlockingQueue)

java併發-阻塞佇列(BlockingQueue) 何為阻塞佇列 A {@link java.util.Queue} that additionally supports operations that wait for the queue to become non-

Java併發程式設計:阻塞佇列BlockingQueue

阻塞佇列BlockingQueue簡介 阻塞佇列BlockingQueue是JDK1.5併發新特性中的內容,阻塞佇列首先是一個佇列,同樣實現了Collection介面。阻塞佇列提供了可阻塞的put和take方法,以及支援定時的poll和offer方法。 阻塞佇列跟普通

Java併發程式設計之執行緒管理基本執行緒同步3

 (上一節的繼續) 2.2 使用Lock機制         Java提供了另外一種機制來同步程式碼塊。它是比synchrozied關鍵字更為強大且彈性的機制。它是基於鎖介面和實現了這個介面的類

Java併發程式設計之執行緒管理高階執行緒同步7

3執行緒同步實用程式 在這一節中,我們將討論如何使用高級別機制去獲得多執行緒的同步(synchronized)。這些高級別機制有下面幾種: Ø  訊號(Semaphores):一個訊號就是一個計數

JAVA併發之BlockingQueue阻塞佇列

前言: 在新增的Concurrent包中,BlockingQueue很好的解決了多執行緒中,如何高效安全“傳輸”資料的問題。通過這些高效並且執行緒安全的佇列類,為我們快速搭建高質量的多執行緒程式帶來極大的便利。本文詳細介紹了BlockingQueue家庭中的

Java併發程式設計之執行緒管理基本執行緒同步6

3.5 在一個鎖中使用多種狀態 一個鎖(Lock)可能和一個或者多個狀態相關聯,這些狀態在Condition介面中已經被宣告好了。這些狀態的作用就是去執行執行緒控制一個鎖或者檢查一個狀態是否為true或者false。如果是false,這個執行緒將被掛起直到其它的執行緒將它們

16-Java併發程式設計:Timer和TimerTask轉載

Java併發程式設計:Timer和TimerTask(轉載)   下面內容轉載自:   其實就Timer來講就是一個排程器,而TimerTask呢只是一個實現了run方法的一個類,而具體的TimerTask需要由你自己來實現,例如這樣: Timer timer =

Postfix常用命令和郵件佇列管理queue

本文主要介紹一下postfix的常用命令及郵件佇列的管理: Postfix有以下四種郵件佇列,均由管理佇列的程序統一進行管理: maildrop:本地郵件放置在maildrop中,同時也被拷貝到incoming中。 incoming:放置正在到達佇列或管理程序尚未發現的郵