日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

非阻塞算法(Lock-Free)的实现

發布時間:2024/2/28 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 非阻塞算法(Lock-Free)的实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 非阻塞的棧
    • 非阻塞的鏈表

非阻塞算法(Lock-Free)的實現

上篇文章我們講到了使用鎖會帶來的各種缺點,本文將會講解如何使用非阻塞算法。非阻塞算法一般會使用CAS來協調線程的操作。

雖然非阻塞算法有諸多優點,但是在實現上要比基于鎖的算法更加繁瑣和負責。

本文將會介紹兩個是用非阻塞算法實現的數據結構。

非阻塞的棧

我們先使用CAS來構建幾個非阻塞的棧。棧是最簡單的鏈式結構,其本質是一個鏈表,而鏈表的根節點就是棧頂。

我們先構建Node數據結構:

public class Node<E> {public final E item;public Node<E> next;public Node(E item){this.item=item;} }

這個Node保存了內存item和它的下一個節點next。

然后我們構建非阻塞的棧,在該棧中我們需要實現pop和push方法,我們使用一個Atomic類來保存top節點的引用,在pop和push之前調用compareAndSet命令來保證命令的原子性。同時,我們需要不斷的循環,以保證在線程沖突的時候能夠重試更新。

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;}}

非阻塞的鏈表

構建鏈表要比構建棧復雜。因為我們要維持頭尾兩個指針。以put方法來說,我們需要執行兩步操作:1. 在尾部插入新的節點。2.將尾部指針指向最新的節點。

我們使用CAS最多只能保證其中的一步是原子執行。那么對于1和2的組合步驟該怎么處理呢?

我們再仔細考慮考慮,其實1和2并不一定要在同一個線程中執行,其他線程在檢測到有線程插入了節點,但是沒有將tail指向最后的節點時,完全幫忙完成這個操作。

我們看下具體的代碼實現:

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);} }

先構建一個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) {//有其他的線程已經插入了一個節點,但是還沒有將tail指向最新的節點tail.compareAndSet(currentTail, tailNext);}else{//沒有其他的線程插入節點,那么做兩件事情:1. 插入新節點,2.將tail指向最新的節點if(currentTail.next.compareAndSet(null, newNode)){tail.compareAndSet(currentTail, newNode);}}}}} }

本文的例子可以參考https://github.com/ddean2009/learn-java-concurrency/tree/master/nonblock

更多精彩內容且看:

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

更多內容請訪問 http://www.flydean.com/java-lock-free/

總結

以上是生活随笔為你收集整理的非阻塞算法(Lock-Free)的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。