天天看點

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,具體代碼如下。

  

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

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

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

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

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

二、Posix互斥鎖

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

下方這個PosixThreadMutex類是Atomic的代碼實作中封裝的Posix互斥鎖。在該代碼實作中主要調用了C語言中的線程互斥鎖的相關函數。下方鎖的使用方式,稍後再聊Atomic類的時候會使用到下方的這個互斥鎖。

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

三、遞歸鎖

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

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

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

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

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

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

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

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

四、Atomic原子操作的具體代碼實作

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

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

ReactiveSwift源碼解析(十一) Atomic的代碼實作以及其中的Defer延遲、Posix互斥鎖、遞歸鎖

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

上述代碼github分享位址:https://github.com/lizelu/TipSwiftForRac  

作者:青玉伏案

出處:http://www.cnblogs.com/ludashi/

本文版權歸作者和共部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

如果文中有什麼錯誤,歡迎指出。以免更多的人被誤導。

收履歷:某網際網路公司,招聘iOS/Android靠譜工程師,入職後,可内部聯系樓主,有小禮品贈送,有意者可郵箱投遞履歷:[email protected]