中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java有鎖并發、無鎖并發和CAS實例分析

發布時間:2022-03-22 17:07:16 來源:億速云 閱讀:180 作者:iii 欄目:大數據

這篇文章主要介紹“Java有鎖并發、無鎖并發和CAS實例分析”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Java有鎖并發、無鎖并發和CAS實例分析”文章能幫助大家解決問題。

有鎖并發

對于大多數程序員(當然我也基本上是其中一員),并發編程幾乎就等價于給相關數據結構加上一個鎖(Mutex)。比如如果我們需要一個支持并發的棧,那最簡單的方法就是給一個單線程的棧加上鎖  std::sync::Mutex  。(加上Arc是為了能讓多個線程都擁有棧的所有權)

   
   
  
use std::sync::{Mutex, Arc};

#[derive(Clone)]
struct ConcurrentStack<T> {
   inner: Arc<Mutex<Vec<T>>>,
}

impl<T> ConcurrentStack<T> {
   pub fn new() -> Self {
       ConcurrentStack {
           inner: Arc::new(Mutex::new(Vec::new())),
       }
   }

   pub fn push(&self, data: T) {
       let mut inner = self.inner.lock().unwrap();
       (*inner).push(data);
   }

   pub fn pop(&self) -> Option<T> {
       let mut inner = self.inner.lock().unwrap();
       (*inner).pop()
   }

}
           
這樣做的好處是顯而易見的:代碼寫起來十分方便,畢竟和單線程版本的幾乎一樣。只需要按照單線程的版本寫完,然后給數據結構加上鎖,然后在必要的時候獲取和釋放(在Rust中基本上是自動的)鎖即可。
那么問題是什么呢?首先不談你可能會忘記獲取和釋放鎖(這一點要感謝Rust,在Rust中幾乎不可能發生),你可能會面臨死鎖的問題(哲學家就餐問題)。然后也不談一些低優先級的任務可能會長期搶占高優先級任務的資源(因為鎖是第一位的),當線程數量比較大的時候,大部分的時間都被用在了同步上(等待鎖能被獲取),性能就會變得非常差。考慮一個大量讀取而偶爾寫入的并發數據庫,如果用鎖去處理,即使數據庫沒有任何更新,每兩個讀之間也需要做一次同步,代價太大!

無鎖并發

于是,大量計算機科學家和程序員就把目光轉向了無鎖(lock-free)并發。無鎖對象:如果一個共享對象保證了無論其他線程做何種操作,總有一些線程會在有限的系統操作步驟后完成一個對其的操作  Her91  。也就是說,至少有一個線程對其操作會取得成效。使用鎖的并發明顯就不屬于這一范疇:如果獲取了鎖的線程被延遲,那么這段時間里沒有任何線程能夠完成任何操作。極端情況下如果出現了死鎖,那么沒有任何線程能夠完成任何操作。

CAS(compare and swap)原語

那大家可能會好奇,無鎖并發要怎么實現呢?有沒有例子呢?在此之前讓我們先看一下一個公認的在無鎖并發中非常重要的原子原語:CAS。CAS的過程是用指定值去比較一儲存值,只有當他們相同時,才會修改儲存值為新的指定值。CAS是個原子操作(由處理器支持,比如x86的compare and exchange (CMPXCHG)),該原子性保證了如果其他線程已經改變了儲存值,那么寫入就會失敗。Rust標準庫中的  std::sync::atomic  中的類型就提供了CAS操作,比如原子指針  std::sync::atomic::AtomicPtr

   
   
  
pub fn compare_and_swap(
   &self,
   current: *mut T,
   new: *mut T,
   order: Ordering
) -> *mut T
           
(在這里,不用糾結ordering是什么,也就是說請盡管忽略忽略  Acquire  ,   Release  ,   Relaxed  )

無鎖棧(天真版)


   
   
  
#![feature(box_raw)]

use std::ptr::{self, null_mut};
use std::sync::atomic::AtomicPtr;
use std::sync::atomic::Ordering::{Relaxed, Release, Acquire};

pub struct Stack<T> {
   head: AtomicPtr<Node<T>>,
}

struct Node<T> {
   data: T,
   next: *mut Node<T>,
}

impl<T> Stack<T> {
   pub fn new() -> Stack<T> {
       Stack {
           head: AtomicPtr::new(null_mut()),
       }
   }

   pub fn pop(&self) -> Option<T> {
       loop {
           // 快照
           let head = self.head.load(Acquire);

           // 如果棧為空
           if head == null_mut() {
               return None
           } else {
               let next = unsafe { (*head).next };

               // 如果現狀較快照并沒有發生改變
               if self.head.compare_and_swap(head, next, Release) == head {

                   // 讀取內容并返回
                   return Some(unsafe { ptr::read(&(*head).data) })
               }
           }
       }
   }

   pub fn push(&self, t: T) {
       // 創建node并轉化為*mut指針
       let n = Box::into_raw(Box::new(Node {
           data: t,
           next: null_mut(),
       }));
       loop {
           // 快照
           let head = self.head.load(Relaxed);

           // 基于快照更新node
           unsafe { (*n).next = head; }

           // 如果在此期間,快照仍然沒有過時
           if self.head.compare_and_swap(head, n, Release) == head {
               break
           }
       }
   }
}
           
我們可以看到,無論是pop還是push思路都是一樣的:先在快照上pop或者是push,然后嘗試用CAS替換原來的數據。如果快照和數據一致,說明這一期間數據沒有被寫操作過,于是更新成功。如果不一致,說明在此期間有其他線程修改過數據,那么一切從頭再來。這就是一個無鎖的棧。似乎一切都已經大功告成了!

內存釋放

確實你可能已經大功告成了,但前提是你在寫Java,或者是其他有GC的語言。現在的問題在于,在Rust這種沒有GC的語言中,pop中
return Some(unsafe { ptr::read(&(*head).data) })
并沒有人去釋放  head  ,這是一個內存泄漏!哎,看來無鎖并發好不容易呢。

關于“Java有鎖并發、無鎖并發和CAS實例分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

论坛| 舟山市| 新邵县| 金门县| 永春县| 哈尔滨市| 胶州市| 凭祥市| 南靖县| 无锡市| 青铜峡市| 星座| 广南县| 巴东县| 庆安县| 通道| 日照市| 前郭尔| 桂林市| 玉树县| 福鼎市| 麻阳| 冷水江市| 宁蒗| 阜宁县| 勃利县| 鹿邑县| 贺兰县| 碌曲县| 庆城县| 亚东县| 余庆县| 海南省| 南陵县| 清河县| 三河市| 迁安市| 麟游县| 贵定县| 柘荣县| 安康市|