分析Java非阻塞算法Lock-Free的實現(xiàn)
非阻塞的棧
我們先使用CAS來構(gòu)建幾個非阻塞的棧。棧是最簡單的鏈?zhǔn)浇Y(jié)構(gòu),其本質(zhì)是一個鏈表,而鏈表的根節(jié)點就是棧頂。
我們先構(gòu)建Node數(shù)據(jù)結(jié)構(gòu):
public class Node<E> { public final E item; public Node<E> next; public Node(E item){ this.item=item; } }
這個Node保存了內(nèi)存item和它的下一個節(jié)點next。
然后我們構(gòu)建非阻塞的棧,在該棧中我們需要實現(xiàn)pop和push方法,我們使用一個Atomic類來保存top節(jié)點的引用,在pop和push之前調(diào)用compareAndSet命令來保證命令的原子性。同時,我們需要不斷的循環(huán),以保證在線程沖突的時候能夠重試更新。
public class ConcurrentStack<E> { AtomicReference<Node<E>> top= new AtomicReference<>(); public void push(E item){ Node<E> newNode= new Node<>(item); Node<E> oldNode; do{ oldNode=top.get(); newNode.next= oldNode; }while(!top.compareAndSet(oldNode, newNode)); } public E pop(){ Node<E> oldNode; Node<E> newNode; do { oldNode = top.get(); if(oldNode == null){ return null; } newNode=oldNode.next; }while(!top.compareAndSet(oldNode, newNode)); return oldNode.item; } }
非阻塞的鏈表
構(gòu)建鏈表要比構(gòu)建棧復(fù)雜。因為我們要維持頭尾兩個指針。以put方法來說,我們需要執(zhí)行兩步操作:1. 在尾部插入新的節(jié)點。2.將尾部指針指向最新的節(jié)點。
我們使用CAS最多只能保證其中的一步是原子執(zhí)行。那么對于1和2的組合步驟該怎么處理呢?
我們再仔細(xì)考慮考慮,其實1和2并不一定要在同一個線程中執(zhí)行,其他線程在檢測到有線程插入了節(jié)點,但是沒有將tail指向最后的節(jié)點時,完全幫忙完成這個操作。
我們看下具體的代碼實現(xiàn):
public class LinkedNode<E> { public final E item; public final AtomicReference<LinkedNode<E>> next; public LinkedNode(E item, LinkedNode<E> next){ this.item=item; this.next=new AtomicReference<>(next); } }
先構(gòu)建一個LinkedNode類。
public class LinkedQueue<E> { private final LinkedNode<E> nullNode= new LinkedNode<>(null, null); private final AtomicReference<LinkedNode<E>> head= new AtomicReference<>(nullNode); private final AtomicReference<LinkedNode<E>> tail= new AtomicReference<>(nullNode); public boolean put(E item){ LinkedNode<E> newNode = new LinkedNode<>(item, null); while (true){ LinkedNode<E> currentTail= tail.get(); LinkedNode<E> tailNext= currentTail.next.get(); if(currentTail == tail.get()){ if (tailNext != null) { //有其他的線程已經(jīng)插入了一個節(jié)點,但是還沒有將tail指向最新的節(jié)點 tail.compareAndSet(currentTail, tailNext); }else{ //沒有其他的線程插入節(jié)點,那么做兩件事情:1. 插入新節(jié)點,2.將tail指向最新的節(jié)點 if(currentTail.next.compareAndSet(null, newNode)){ tail.compareAndSet(currentTail, newNode); } } } } } }
以上就是分析Java非阻塞算法Lock-Free的實現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Java非阻塞算法Lock-Free的實現(xiàn)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java?實現(xiàn)獲取指定位置后的第一個數(shù)字
這篇文章主要介紹了java?實現(xiàn)獲取指定位置后的第一個數(shù)字,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01java驗證用戶是否已經(jīng)登錄 java實現(xiàn)自動登錄
這篇文章主要介紹了java驗證用戶是否已經(jīng)登錄,java實現(xiàn)自動登錄,感興趣的小伙伴們可以參考一下2016-04-04mybatis-plus的selectById(或者selectOne)在根據(jù)主鍵ID查詢實體對象的時候偶爾會出現(xiàn)nul
這篇文章主要介紹了mybatis-plus的selectById(或者selectOne)在根據(jù)主鍵ID查詢實體對象的時候偶爾會出現(xiàn)null的問題記錄,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Spring boot 在idea中添加熱部署插件的圖文教程
這篇文章主要介紹了Spring boot 在idea中添加熱部署插件的圖文教程,本文通過圖文并茂的形式給大家展示具體步驟,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10String實例化及static final修飾符實現(xiàn)方法解析
這篇文章主要介紹了String實例化及static final修飾符實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09使用Java代碼將IP地址轉(zhuǎn)換為int類型的方法
這篇文章主要介紹了使用Java代碼將IP地址轉(zhuǎn)換為int類型的方法,這也是各大計算機考試和ACM以及面試的常見基礎(chǔ)問題,需要的朋友可以參考下2015-08-08