1. 程式人生 > >ReactiveSwift原始碼解析(十一) Atomic的程式碼實現以及其中的Defer延遲、Posix互斥鎖、遞迴鎖

ReactiveSwift原始碼解析(十一) Atomic的程式碼實現以及其中的Defer延遲、Posix互斥鎖、遞迴鎖

本篇部落格我們來聊一下ReactiveSwift中的原子性操作,在此內容上我們簡單的聊一下Posix互斥鎖以及遞迴鎖的概念以及使用場景。然後再聊一下Atomic的程式碼實現Atomic主要負責多執行緒下的原子操作,負責共享資源的同步一致性。而在Atomic中就是使用到了Posix互斥鎖和遞迴鎖。在聊上述內容之前,我們先來回顧一下Swift語言中延遲執行defer的使用方式,在之前Swift程式設計的相關部落格中也涉及到了defer的使用方式。defer因為Atomic使用到了延遲操作,所以下方我們再做一個defer的簡單回顧。

一、Defer延遲執行

在本篇部落格之所以聊defer延遲執行

,是因為在Atomic的程式碼實現中,使用了defer{}來為操作加的鎖。具體的說是在操作前進行加鎖,然後緊接著使用defer{}進行解鎖,稍後我們會進行介紹。Swift中的Defer延遲執行是比較常用的,其用法也是比較簡單的。下方就是我們列舉了一個示例,該示例比較簡單。首先我們輸出a,然後使用defer塊執行輸出b的語句,然後就是輸出c,最後是使用defer塊輸出d,具體程式碼如下。

  

在看上述程式碼輸出結果時,我們可以先預測一下輸出結果,是輸出“abcd”還是“acbc”還是“acdb”呢?下方就是上述程式碼片段的輸出結果。從下方程式碼片段中我們不難看出,其結果為“acdb”。從結果中我們不難看出defer{}塊的執行順序是在該作用域結束之前從後往前執行。

  

根據上述程式碼片段以及輸出結果,我們可以畫出下方這個執行簡圖,如下所示。因為下方這個簡圖並不複雜,在此就不做過多贅述了。

  

二、Posix互斥鎖

互斥鎖的概念就不做過多贅述了,簡單的說就是防止多個執行緒同時修改一塊共享區域,導致資料不同步的情況發生而新增的鎖。互斥鎖的互斥是執行緒的互斥,也就是說新增互斥鎖的程式碼塊在同一個時間點上只允許一個執行緒對這塊共享區域進行操作,其他執行緒若想對該塊區域進行操作的話,需要等待之前的互斥鎖開啟後方可進入。

下方這個PosixThreadMutex類是Atomic的程式碼實現中封裝的Posix互斥鎖。在該程式碼實現中主要呼叫了C語言中的執行緒互斥鎖的相關函式。下方鎖的使用方式,稍後再聊Atomic類的時候會使用到下方的這個互斥鎖。

  

三、遞迴鎖

接下來我們來看一下遞迴鎖,在Atomic的程式碼實現中也使用到了遞迴鎖。“遞迴鎖”顧名思義就是在遞迴中使用的鎖,普通鎖在一個執行緒中是不能被重用的,也就是說一個普通鎖被上鎖後,你就不能再次呼叫上鎖的方法了,這樣會出問題的。等普通鎖被解鎖後,你才可以對其進行上鎖。針對普通鎖的不可重用性,我們給出了下方示例,如下所示。

  

上述程式碼片段比較簡單,對普通鎖連續執行了兩次lock,然後執行我們的程式碼塊,之後就是執行了兩次unlock。該程式碼使用普通鎖的步驟其實是與遞迴函式中使用普通鎖的場景是一樣的。當遞迴實現函式是,執行第一次遞迴時,添加了一個普通鎖,在鎖未開啟時,第二次遞迴時又會執行一下上鎖。這種場景與上述程式碼片段是一樣的。因為普通鎖在同一個執行緒中的不可重用性,所以上述程式碼會產生死鎖DeadLock。下方截圖就是上述程式碼片段所執行的結果: 

  

我們將上述程式碼中的NSLock普通鎖修改成NSRecursiveLock遞迴鎖後,如下。下方的程式碼就可以正確執行。因為遞迴鎖可以在同一個執行緒中重複的使用。具體如下所示:

  

既然是遞迴鎖,那麼接下來我們就在遞迴函式中來使用一下遞迴鎖。在遞迴函式執行使用鎖時,本質上是多次使用一個鎖。也就是在一個鎖未上鎖時再次對其上鎖。下方就是遞迴鎖在遞迴函式中使用的簡單示例。

  

四、Atomic原子操作的具體程式碼實現

聊完互斥鎖和遞迴鎖後,接下來我們來看一下ReactiveSwift中的原子操作Atomic類的具體程式碼實現。Aotmic中使用了上述我們聊的Posix互斥鎖來進行的原子操作。下方就是Atomic類的程式碼實現。

從下方程式碼片段中我們不難看出,在value讀取和修改時都會進行加鎖和解鎖操作。當然,解鎖的程式碼是放在defer{}的語句塊中進行操作的。在Atomic.swift檔案中還有一個RecursiveAtomic類,也就是負責遞迴原子操作的。RecursiveAtomicAtomic類的不同之處在於前者使用的是遞迴鎖,負責在遞迴操作時保持原子操作。而後者使用的是互斥鎖。RecursiveAtomic的程式碼與Atomic類的程式碼類似,在此就不做過多贅述了。

  

今天的部落格就先到這兒,下篇部落格我們會繼續解析ReactiveSwift框架中的其他內容。