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

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

讀取 rec 用法 互斥鎖 ive defer mic 步驟 問題

本篇博客我們來聊一下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框架中的其他內容。

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

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