1. 程式人生 > >JAVA 1.7併發之LinkedTransferQueue原理理解

JAVA 1.7併發之LinkedTransferQueue原理理解

昨天剛看完BlockingQueue覺得好高階啊,今天掃到1.7就發現了升級版。。。。

就是作者的論文啦,純英文。。。比較難啃,但是我覺得邏輯上比看程式碼容易理解,其實程式碼什麼u啊h啊看得很混

LinkedTransferQueue

起源: 我覺得是這樣的,之前的BlockingQueue是對 讀取 或者 寫入 鎖定整個佇列,所以在比較繁忙的時候,各種鎖比較耗時

而當時有一個SynchronizedQueue其實不能叫Queue,因為只能放一個物件,要麼有一個物件在等人拿,要麼有一個空等人放

根據這個原理,誕生了LinkedTransferQueue,利用CompareAndSwap進行一個無阻塞的佇列,針對每一個

操作進行處理樣大家就不用搶得那麼辛苦了

資料結構

在類的內部保持著一個棧,基本單位是node,根據 hasData區分裡面有兩種元素,要麼是 Data 要麼是 Reservation,不會同時存在

並且有一個變數head指向最前面的node,沒東西則是null

Node

{

  isData    是不是資料,是的話item放具體東西

  item   如果不是資料則為null

  next   下一個節點

  waiter  如果不是資料則是reservation,有一個執行緒在等待

}

過程:

整個存取過程分成兩部分

 1:MATCH(原節點,新節點)

for (;;) {                            // restart on append race

            for (Node h = head, p = h; p != null;) { // 如果頭結點為空則跳過,非空進去找第一個可用節點
                boolean isData = p.isData;
                Object item = p.item;
                if (item != p && (item != null) == isData) { // 判斷原節點可用性,如data的item應該是數值,如果是null則表明用過了
                    if (isData == haveData)   // 兩個節點是相同型別,不用match了,去下一步
                        break;
                    if (p.casItem(item, e)) { // 節點不同型別,match成功,更改原節點item,表明不可用
                        for (Node q = p; q != h;) {//什麼,我居然不是head節點了?我要讓它指向我!
                            Node n = q.next;  // update by 2 unless singleton
                            if (head == h && casHead(h, n == null ? q : n)) {
                                h.forgetNext();
                                break;
                            }                 // advance and retry
                            if ((h = head)   == null ||
                                (q = h.next) == null || !q.isMatched())
                                break;        // unless slack < 2
                        }
                        LockSupport.unpark(p.waiter);//根據原節點的型別,reservation則叫人收貨,data則叫null收貨
                        return LinkedTransferQueue.<E>cast(item);//根據原節點的型別,reservation則返回null,data則返回資料
                    }
                }
                Node n = p.next;//下一個節點
                p = (p != n) ? n : (h = head); // Use head if p offlist
            }

  重點是找出第一個可用節點,如果是null則跳過,如果與進來的節點相同(本來就有data,還放data)也跳過,如果不同(本來是data,現在是reservation,返回data值 / 本來是reservation,現在是data,叫人來收貨,返回reservation值=空)

 2:處理節點

if (how != NOW) {                 // No matches available
                if (s == null)
                    s = new Node(e, haveData);
                Node pred = tryAppend(s, haveData);//嘗試新增新node
                if (pred == null)
                    continue retry;           // 不成功則重試整個過程
                if (how != ASYNC)
                    return awaitMatch(s, pred, e, (how == TIMED), nanos);//根據引數,等不等別人放資料,拿資料,等多久
            }
            return e; // not waiting

  MATCH失敗了才會進入這個環節,把新節點放進棧內,並根據引數決定立刻返回或者等待返回

EXAMPLES

1:Head->Data    Input->Data

Match:      根據他們的屬性 發現 cannot match ,因為是同類的

處理節點:   所以把新的data放在原來的data後面,然後head往後移一位,Reservation同理

HEAD=DATA->DATA

2:Head->Data    Input->Reservation  (取資料)

Match:      成功match,就把Data的item變為reservation的值(null,有主了),並且返回資料。

處理節點:  沒動,head還在原地

HEAD=DATA(用過)

3:Head->Reservation  Input->Data(放資料)

Match:       成功match,就把Reservation的item變為Data的值(有主了),並且叫waiter來取

處理節點:  沒動

HEAD=RESERVATION(用過)

總結:LinkedTransferQueue通過CAS嘗試放入data或增加reservation。

消耗小於把整個佇列鎖掉,但是在併發特別高的情況下大家搶著嘗試一樣會影響速度

至於為什麼跨過了1.6到1.7這個類才出現我覺得有點神奇

簡單用法介紹------------------------------------------------------------------------------------------------------

存:

put();   放元素進去佇列,注意佇列是可以無限長的

add();   同上

transfer();  這個是重點,如果佇列中有人發現有人在等,則直接給那個人(有一個引數waiter指定了在等的執行緒)

如果沒人在等,就放進佇列

取:

poll();  立即返回,如果沒有元素就是空

take(); 如果沒有元素,那就等

PS:最好是用poll然後自己處理空的狀況,如果全是take然後又遲遲沒有東西,那就一堆記憶體在等了。

相關推薦

JAVA 1.7併發LinkedTransferQueue原理理解

昨天剛看完BlockingQueue覺得好高階啊,今天掃到1.7就發現了升級版。。。。 就是作者的論文啦,純英文。。。比較難啃,但是我覺得邏輯上比看程式碼容易理解,其實程式碼什麼u啊h啊看得很混 LinkedTransferQueue 起源: 我覺得是這樣的,之前的BlockingQueue

JAVA筆記 —— HashMap(1.7) 底層實現原理

HashMap 底層實現原理     兩年前,我總覺得很多東西會用就行,不喜歡總結,不喜歡深入瞭解,這或許就是因為當時太懶。一年前,我覺得必須要把在工作積累到的東西、遇到的問題及解決方法給總結記錄下來,以便快速提升自己,所以從那時候起就開始寫 txt 文字,做一些簡單記錄

【本人禿頂程式設計師】Java併發CAS原理分析

←←←←←←←←←←←← 快,點關注! CAS,compare and swap的縮寫,中文翻譯成比較並交換 在java語言之前,併發就已經廣泛存在並在伺服器領域得到了大量的應用。所以硬體廠商老早就在晶片中加入了大量直至併發操作的原語,從而在硬體層面提升效率。在intel的CPU中,

JAVA筆記 —— HashMap(1.7) 底層實現原理

HashMap 底層實現原理     兩年前,我總覺得很多東西會用就行,不喜歡總結,不喜歡深入瞭解,這或許就是因為當時太懶。一年前,我覺得必須要把在工作積累到的東西、遇到的問題及解決方法給總結記錄下來,以便快速提升自己,所以從那時候起就開始寫 txt 文字,做一些簡單記錄。

Dynamic Web Module 3.1 requires Java 1.7 or newer. 錯誤解決方案

pom.xml文件 artifact logs per group -s conf 你會 cti 在寫代碼的時候工程出現了這樣奇怪的bug很是蛋疼啊,經過查詢解決方法,終於解決了這些個問題。 下面是解決問題的方法,和大家分享一下 (1)確定你的java工程配置使用了java

java 1.7 1.8新特性

val row def jce arr app 線程安全 動態 adl 在JDK1.7的新特性方面主要有下面幾方面的增強:1.jdk7語法上1.1二進制變量的表示,支持將整數類型用二進制來表示,用0b開頭。1.2 Switch語句支持string類型1.3 Try-with

Java 1.7 ThreadPoolExecutor源代碼解析

bstr check article bsp targe locked 退出 fin exec 相比1.6,1.7有些變化: 1、 添加了一個TIDYING狀態。這個狀態是介於STOP和TERMINATED之間的。假設運行完terminated鉤

Java 1.7 NQuery

lin tin offset inter package nio create leg res package org.rx.common; import java.lang.reflect.Array; import java.util.*; /**

Java 1.7 ThreadPoolExecutor源碼解析

chang 再次 change 維護 ble cep 調用 failure 獲取 相比1.6,1.7有些變化: 1、 增加了一個TIDYING狀態,這個狀態是介於STOP和TERMINATED之間的,如果執行完terminated鉤子函數後狀態就變成TERMI

Eclipse Maven 編譯錯誤 Dynamic Web Module 3.1 requires Java 1.7 or newer 解決方案

  1.開啟這個檢視,kanyi看一下javaSE版本 2.還錯把這個搞上去 <build>   <plugins>        <plugin>      

定時刪除一個月前web伺服器上的垃圾檔案(臨時檔案)使用 java 1.7 Files 進行操作

  ​ import java.io.File; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitResult; import java.ni

同時安裝Java 1.71.8

以前先安裝的java1.7 大部分程式應該都是隻支援1.7 不支援1.8 但是因為要跑一個別人的專案 要求是java1.8 所以想在電腦上同時裝1.7和1.8 到官網上下載1.8 安裝 安裝完成後 並沒有配置環境變數 但是發現java -version變成1.8了 要預設是

解決Dynamic Web Module 3.1 requires Java 1.7 or newer

        概述:使用maven構建web專案時,經常會遇見這個問題,問題原因報錯講述的很清晰明瞭,就是web模組需要使用java1.7及以後的版本,目前的版本不符合。因而只需要修改java版本

Java學習整理系列ThreadLocal的理解

ThreadLocal概念 ThreadLocal是解決執行緒安全問題一個很好的思路,它通過為每個執行緒提供一個獨立的變數副本解決了變數併發訪問的衝突問題。在很多情況下,ThreadLocal比直接使用synchronized同步機制解決執行緒安全問題更簡單,更方便,且結果

20.Spring-Boot中RabbitMQ的使用概念原理理解(重要)

RabbitMQ 即一個訊息佇列,主要是用來實現應用程式的非同步和解耦,同時也能起到訊息緩衝,訊息分發的作用。 AMQP,即Advanced Message Queuing Protocol,一個提供統一訊息服務的應用層標準高階訊息佇列協議,是應用層協議的一個開放標準,為面向

深入理解Java併發synchronized實現原理

關聯文章: 本篇主要是對Java併發中synchronized關鍵字進行較為深入的探索,這些知識點結合博主對synchronized的個人理解以及相關的書籍的講解(在結尾參考資料),如有誤處,歡迎留言。 執行緒安全是併發程式

深入理解 Java 併發 synchronized 實現原理

關聯文章深入理解Java型別資訊(Class物件)與反射機制深入理解Java列舉型別(enum)深入理解Java註解型別(@Annotation)深入理解Java併發之synchronized實現原理本篇主要是對Java併發中synchronized關鍵字進行較為深入的探索,這些知識點結合博主對synchro

扒一扒系列開發中常用的Java集合類(ArrayList篇 jdk 1.7)

mda des obj 初始設置 onu util private 內部 會有 關於這個系列,因為開發主要用的是java語言,一直想寫寫java開發中常用的一些類(雖然這才是開始的第三篇>_<),所有就起了“扒一扒”系列。這個系列會有框架

java併發 CopyOnWriteArrayList的原理和使用方法

描述 CopyOnWriteArrayList:CopyOnWriteArrayList這是一個ArrayList的執行緒安全的變體,其原理大概可以通俗的理解為:初始化的時候只有一個容器,很常一段時間,這個容器資料、數量等沒有發生變化的時候,大家(多個執行緒),都是讀取(假設這段時間裡只

Java 併發程式設計Volatile原理剖析及使用

Java 併發程式設計之Volatile原理剖析及使用 在開始介紹Volatile之前,回顧一下在併發中極其重要的三個概念:原子性,可見行和有序性 原子性: 是指一個操作不可以被中斷.比如賦值操作a=1和返回操作return a,這樣的操作在JVM中只需要一步就可以完成,因此