本篇博客咱们来聊一下ReactiveSwift中的原子性操做,在此内容上咱们简单的聊一下Posix互斥锁以及递归锁的概念以及使用场景。而后再聊一下Atomic的代码实现。Atomic主要负责多线程下的原子操做,负责共享资源的同步一致性。而在Atomic中就是使用到了Posix互斥锁和递归锁。在聊上述内容以前,咱们先来回顾一下Swift语言中延迟执行defer的使用方式,在以前Swift编程的相关博客中也涉及到了defer的使用方式。defer由于Atomic使用到了延迟操做,因此下方咱们再作一个defer的简单回顾。git
1、Defer延迟执行github
在本篇博客之因此聊defer延迟执行,是由于在Atomic的代码实现中,使用了defer{}来为操做加的锁。具体的说是在操做前进行加锁,而后紧接着使用defer{}进行解锁,稍后咱们会进行介绍。Swift中的Defer延迟执行是比较经常使用的,其用法也是比较简单的。下方就是咱们列举了一个示例,该示例比较简单。首先咱们输出a,而后使用defer块执行输出b的语句,而后就是输出c,最后是使用defer块输出d,具体代码以下。编程
在看上述代码输出结果时,咱们能够先预测一下输出结果,是输出“abcd”仍是“acbc”仍是“acdb”呢?下方就是上述代码片断的输出结果。从下方代码片断中咱们不难看出,其结果为“acdb”。从结果中咱们不难看出defer{}块的执行顺序是在该做用域结束以前从后往前执行。swift
根据上述代码片断以及输出结果,咱们能够画出下方这个运行简图,以下所示。由于下方这个简图并不复杂,在此就不作过多赘述了。多线程
2、Posix互斥锁框架
互斥锁的概念就不作过多赘述了,简单的说就是防止多个线程同时修改一块共享区域,致使数据不一样步的状况发生而添加的锁。互斥锁的互斥是线程的互斥,也就是说添加互斥锁的代码块在同一个时间点上只容许一个线程对这块共享区域进行操做,其余线程若想对该块区域进行操做的话,须要等待以前的互斥锁打开后方可进入。函数
下方这个PosixThreadMutex类是Atomic的代码实现中封装的Posix互斥锁。在该代码实现中主要调用了C语言中的线程互斥锁的相关函数。下方锁的使用方式,稍后再聊Atomic类的时候会使用到下方的这个互斥锁。spa
3、递归锁线程
接下来咱们来看一下递归锁,在Atomic的代码实现中也使用到了递归锁。“递归锁”顾名思义就是在递归中使用的锁,普通锁在一个线程中是不能被重用的,也就是说一个普通锁被上锁后,你就不能再次调用上锁的方法了,这样会出问题的。等普通锁被解锁后,你才能够对其进行上锁。针对普通锁的不可重用性,咱们给出了下方示例,以下所示。blog
上述代码片断比较简单,对普通锁连续执行了两次lock,而后执行咱们的代码块,以后就是执行了两次unlock。该代码使用普通锁的步骤实际上是与递归函数中使用普通锁的场景是同样的。当递归实现函数是,执行第一次递归时,添加了一个普通锁,在锁未打开时,第二次递归时又会执行一下上锁。这种场景与上述代码片断是同样的。由于普通锁在同一个线程中的不可重用性,因此上述代码会产生死锁DeadLock。下方截图就是上述代码片断所执行的结果:
咱们将上述代码中的NSLock普通锁修改为NSRecursiveLock递归锁后,以下。下方的代码就能够正确执行。由于递归锁能够在同一个线程中重复的使用。具体以下所示:
既然是递归锁,那么接下来咱们就在递归函数中来使用一下递归锁。在递归函数执行使用锁时,本质上是屡次使用一个锁。也就是在一个锁未上锁时再次对其上锁。下方就是递归锁在递归函数中使用的简单示例。
4、Atomic原子操做的具体代码实现
聊完互斥锁和递归锁后,接下来咱们来看一下ReactiveSwift中的原子操做Atomic类的具体代码实现。Aotmic中使用了上述咱们聊的Posix互斥锁来进行的原子操做。下方就是Atomic类的代码实现。
从下方代码片断中咱们不难看出,在value读取和修改时都会进行加锁和解锁操做。固然,解锁的代码是放在defer{}的语句块中进行操做的。在Atomic.swift文件中还有一个RecursiveAtomic类,也就是负责递归原子操做的。RecursiveAtomic与Atomic类的不一样之处在于前者使用的是递归锁,负责在递归操做时保持原子操做。然后者使用的是互斥锁。RecursiveAtomic的代码与Atomic类的代码相似,在此就不作过多赘述了。
今天的博客就先到这儿,下篇博客咱们会继续解析ReactiveSwift框架中的其余内容。
上述代码github分享地址:https://github.com/lizelu/TipSwiftForRac