軟體事務記憶體導論 十一 STM的侷限性

2021-09-23 21:45:56 字數 4016 閱讀 8335

stm消除了顯式的同步操作,所以我們在寫**時就無需擔心自己是否忘了進行同步或是否在錯誤的層級上進行了同步。然而stm本身也存在一些問題,比如在跨越記憶體柵欄失敗或遭遇競爭條件時我們捕獲不到任何有用的資訊。我似乎可以聽到你內心深處那個精明的程式設計師在抱怨「怎麼會這樣啊?」。確實,stm是有其侷限性的,否則本書寫到這裡就應該結束了。stm只適用於寫衝突非常少的應用場景,如果你的應用程式存在很多寫操作競爭,那麼我們就需要在stm之外尋找解決方案了。

下面讓我們進一步討論stm的侷限性。stm提供了一種顯式的鎖無關程式設計模型,這種模型允許多個事務併發地執行,並且在沒有發生衝突時所有事務都能毫無滯礙地執行,所以相對其他程式設計模型而言stm可以提供更好的併發性和執行緒安全方面的保障。當事務對相同物件或資料的寫訪問發生衝突時,只有乙個事務能夠順利完成,其他事務都會被自動重做。這種重做機制延緩了寫操作衝突時競爭失敗的那些寫者的執行,但卻提公升了讀者和競爭操作的勝利者的執行速度。當對於相同物件的併發寫操作不頻繁時,其效能就不會受到太大影響。但是隨著衝突的增多,程式整體效能將因此變得越來越差。

如果對相同資料有很高的寫衝突概率,那麼我們的應用程式輕則寫操作變慢,重則會因為重試太多次而導致失敗。目前在本章我們所看到的例子都是在展示stm的優勢,但是在下面的例子中我們將會看到,雖然stm是易於使用的,但也並非在所有應用場景下都能得到理想的結果。

在4.2節的示例中,當多個執行緒同時訪問多個目錄時,我們使用atomiclong來對檔案大小的併發更新操作進行同步。此外,如果需要同時更新多個變數,我們也必須依賴同步才能完成。雖然表面看起來使用stm對這段**進行重構似乎是個不錯的選擇,但大量的寫衝突卻使得stm不適用於這個應用場景。下面就讓我們將上述計算目錄大小的程式改用stm實現,並觀察其執行結果是否如我們所預料的那麼差。

在下面的**中,我們沒有使用atomiclong,而是採用了akka託管引用作為filesizewstm的屬性字段。

1publicclassfilesizewstm

7}.execute();

8}

在完成上述定義之後,訪問目錄和計算檔案大小的函式就相對容易多了,我們只需要把程式中的atomiclong替換成託管引用就好。

01privatevoidfindtotalsizeoffilesindir(finalfile file)

09}.execute();

10}else

19});

20}

21}

22}

23if(updatependingfilevisits(-1) ==0) latch.countdown();

24}catch(exception ex)

28}

最後,我們還需要寫一些建立executor服務池和使程式執行起來的**:

01privatelonggettotalsizeoffile(finalstring filename)

02throwsinterruptedexceptionfinally

12}

13publicstaticvoidmain(finalstring args)throwsinterruptedexception

20}

由於我懷疑這段**跑起來之後可能有問題,所以如果在程式中抓到事務失敗所導致的異常,我就會結束掉整個應用程式。

根據事務的定義,如果變數的值在事務提交之前發生了改變,那麼事務將會自動重做。在本例中,多個執行緒會同時競爭修改這兩個可變變數,從而導致程式執行變慢或失敗。我們可以在多個不同的目錄上分別執行上述示例**來進行觀察,下面就列出了該示例程式在我的電腦上計算/etc和/usr這兩個目錄的輸出結果:

1total file sizefor/etc

2total size:2266408

3time taken:0.537082

4total file sizefor/usr

5too many retries on transaction'defaulttransaction', maxretries =1000

6too many retries on transaction'defaulttransaction', maxretries =1000

7too many retries on transaction'defaulttransaction', maxretries =1000

8...

從輸出結果來看,stm版本對於/etc目錄的計算結果與之前使用atomiclong的那個版本是完全相同的。但是由於會產生過多的重試操作,所以stm版本的執行時間要比後者慢乙個數量級。而遍歷/usr目錄的運**況則更為糟糕,有相當多的事務超過了預設的最大重試限制。雖然我們的邏輯是一抓到異常就會立即終止整個程式,但由於多個事務是併發執行的,所以在程式真正停止之前我們還是能看到多條錯誤資訊輸出到控制台。

由於大量執行緒會同時嘗試更新totalsize變數,所以計算目錄大小示例在實際執行過程中會產生非常頻繁的寫衝突,這也就意味著stm不適合於解決此問題。事實上,當讀操作十分頻繁且寫衝突被控制在合理範圍內時,stm的效能還是不錯的,同時還能幫程式設計師免除顯式同步的負擔。但是在不考慮一般程式中常見的其他導致延時問題的前提下,如果待解決問題中含有大量寫衝突,那就請不要使用stm,而是考慮採用我們在第8章中將會討論的actor模型來避免同步操作。

stm是乙個針對併發問題的非常強大的程式設計模型,該模型有很多優點:

該模型適用於對相同資料存在併發讀且寫衝突不頻繁的應用場景。

如果應用程式的資料訪問方式符合stm的適用範疇,則stm就為我們提供了一種處理共享可變性的高效解決方案。而如果我們的應用場景裡寫衝突非常多,我們可能就會更傾向於使用將在第8章中討論的基於角色(actor)的模型。但在下一章,還是讓我們先學習一下如何在其他jvm上的語言中使用stm程式設計模型。 

事務和事務記憶體

看到solidot報道,英特爾下一代haswell處理器硬體支援事務記憶體,感覺有點小意外。其實很早以前 2009年 我就對事務記憶體關注過一段時間,當時,號稱要支援的事務記憶體的處理器只有 據我所知 只有sun公司的rock處理器,可是這個rock,一再跳票,跳到sun隕落也沒發布,到現在,ora...

軟體工程導論

現在由於房價的高漲,越來越多的人選擇了租房子,尤其是剛畢業的大學生。由此,如果有乙個專門的 或者軟體能夠提供租房的資訊,那麼它所產生的影響無疑是比較大的。房屋租賃管理系統的功能性需求包括 在房屋租賃管理系統中,設定乙個管理員,管理員有修改 新增 刪除系統中任何資料的許可權 普通使用者可以直接進入系統...

軟體工程導論

讀書筆記1 1 軟體工程 軟體工程將系統化的,規範化的,可度量的方法應用於軟體開發,執行和維護,將工程化應用於軟體方法。軟體工程的基本原理 分階段的生存週期計畫嚴格管理 分若干階段切實可行的計畫完成 階段評審 及早發現錯誤,減少成本 嚴格的產品控制 不得隨意更改需求 結果能清楚審查 採用現代程式設計...