.NET:防止並發修改 之 離線樂觀鎖代碼示例(菜鳥必讀)


背景

小明和小強同時簽出了源代碼,如果小強先提交,那么提交成功是合理的,接着小明提交了修改,這時源代碼服務器就會告訴小明有人在他讀取之后做了修改,問他如何處理,源代碼服務器會讓小明把修改合並后再提交。這就是樂觀鎖策略,當然源代碼服務也可以配置為悲觀鎖以避免並行修改。

合理的規避並發修改是企業應用中不能回避的問題,但現實場景是,很多團隊都回避這個問題。今天我介紹一下如何使用離線樂觀鎖處理並發修改。

相關文章:再談在線悲觀鎖、離線悲觀鎖、在線樂觀鎖和離線樂觀鎖

思路

CAS:Compare And Swap,只有當要修改的值在我讀取后沒有被修改,才會被交換(修改)。

CAS是多線程領域的術語,比如:無鎖的環形隊列就是基於這個實現的。因為CAS的思想和樂觀鎖的思想一致,我就借用一下。

看一下離線樂觀鎖的應用場景:

上圖包含了如下信息:

一、讀取線程A1和修改線程A2是不同的線程,因此才叫離線。例如:表單的讀取數據和修改。

二:CAS的Compare比較的是版本號,Swap的是整條記錄。例如:EntityFramework允許你指定哪些屬性是版本屬性。

代碼示例

設置版本字段

CAS

 1         /// <summary>
 2         /// 執行修改。
 3         /// </summary>
 4         public void Handle(TCommand command)
 5         {
 6             var unitOfWork = ServiceLocator.Current.GetInstance<TUnitOfWork>();
 7 
 8             unitOfWork
 9                 .GetRepository<TRepository>()
10                 .MarkAsModified(command.Aggregate);
11 
12             unitOfWork.Commit();
13         }

運行效果

注意事項

一、示例中我直接將讀取線程讀取的數據,離線修改后傳遞個修改線程了,這樣兩個線程只有一次讀取邏輯,這保證了CAS中Compare的正確性。有些場景你可能需要在修改線程中也進行一次讀取,然后將UI層修改的數據合並過來,這種情況就要注意了,必須要手工指定Compare操作使用第一個線程讀取的版本號,否則會使用第二次讀取的版本號。

二、樂觀離線鎖只適合重來成本很低的場景,否則用戶編輯了兩個小時,你告訴他出現並發問題了,他會瘋的。這種成本很高的操作適合“離線悲觀鎖”。

備注

我就是一個行動跟不上思維的人,因為懶惰,我沒有全面的在項目中采用樂觀鎖,下一個項目一定全面實施。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM