2018 ing!一起努力呀!
<若有问题还请多多指正>
基础概念:
1、进程and线程
1.1 进程
定义:
狭义定义:进程是正在运行的程序的实例
广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
特征:
- 动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生、动态消亡的;
- 并发性:任何进程都可以同其他进程一起并发执行;
- 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
- 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进;
- 结构特征:进程由程序、数据和进程控制块三部分组成,多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。
状态:就绪、运行、阻塞
特点:
第一:进程是一个实体,每一个进程都有它自己的地址空间;
地址空间一般包括:文本区域(text region)存储处理器执行的代码;数据区域(data region):存储变量和进程执行期间使用的动态分配的内存;堆栈(stack region)存储着活动过程中调用的指令和本地变量。
第二:进程是一个“执行中的程序”。
1.2线程
定义:程序执行流的最小单元,有时称为轻量级进程。
组成:一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
线程是进程中一个实体,是被系统对立调度和分派的基本单位,线程自己不拥有资源,只拥有一点在运行中必不可少的资源,它可以和同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。由于线程之间的相互制约,所以线程在运行中呈现出间断性。每一个程序至少有一个线程!
1.3进程和线程的对比:
- 线程是独立运行和独立调度的基本单位,进程是分配资源的最小单位;
- 进程间相互独立,同一进程内的各个线程资源共享;
- 某进程内的线程其他进程不可见;
- 进程间通信(IPC,常见方法是:消息队列,信号量,网络socket等),线程间可以直接读写进程数据段(如全局变量)来进行通信(需要进程同步和互斥手段的辅助,以确保数据的一致性)
- 线程上下文切换比进程上下文切换要快的多。
2、队列和执行方式
2.1串行队列:所有任务会在一条线程中执行(有可能是在当前线程也有可能是新开辟的线程),并且一个任务执行完毕后,才开始执行下一个任务。(等待完成)
2.2并行队列:可以开启多条线程并执行任务(但不一定开启新的线程) ,并且当一个任务方法指定线程开始执行,下一个任务就可以开始执行了。(等待发生)
2.3主队列:系统为我们创建好的一个串行队列,它管理必须在主线程中执行的任务。
2.4全局队列:系统为我创建好的一个并行队列,使用起来和我们自己创建的并行队列无本质差别。
2.5同步执行:在当前线程执行任务,不会开辟新的线程。必须等到block函数执行完毕之后,dispatch函数才会返回。
2.6异步执行:可以在新的线程中执行任务,但不一定会开辟新的线程。Dispatch函数会立即返回,然后block函数在后台异步执行。
个人理解:
串行队列必须是前一个任务执行完毕才开始执行下一个任务(无论这个任务是同步还是异步),同步或异步在串行队列中的影响是:是否与正在执行的外部函数(本任务之外的函数)有影响,同步需要等到本任务执行完毕才继续执行外部函数,异步不影响外部函数的执行;
如果多个异步执行加入到串行队列中,这多个任务也会按照家务的顺序执行(异步可能会开辟新的线程,不是一定开辟);
串行队列+同步任务:不会开启新的线程,任务逐步完成。
串行队列+异步任务:可能开启新的线程,任务逐步完成。
并发队列+同步任务:不会开启新的线程,任务逐步完成。
并发队列+异步任务:开启新的线程,任务同步完成。
会造成死锁的几种情况
- 主线程中同步执行任务会造成死锁。
- 串行队列开启异步任务后嵌套同步任务造成死锁:
- 因为串行队列中线程是有执行顺序的,需要等上面开启的异步任务执行完毕,才会执行下面开启的同步任务。而上面的异步任务还没执行完,要到下面的大括号才算执行完毕,而下面的同步任务已经在抢占资源了,就会发生死锁。
- 串行队列开启同步任务后嵌套同步任务造成死锁:
- 因为串行队列中线程是有执行顺序的,需要等上面开启的同步任务执行完毕,才会执行下面开启的同步任务。而上面的同步任务还没执行完,要到下面的大括号才算执行完毕,而下面的同步任务已经在抢占资源了,就会发生死锁。
备注:
串行队列开启同步任务后嵌套异步任务不造成死锁:
开启异步,就会开启一个新的线程,不会阻塞线程。
---------------------------------------------我是分割线----- ----- ----- ----- ----- ----- ----- -----
---------------------------------------------我是7.14更新----- --- ----- ----- ----- ----- ----- -----
关于之上的实例分析:
//首先分别初始化一个串行队列和一个并行队列 //串行队列 self.serialQueue = dispatch_queue_create("serialQueue.ys.com", DISPATCH_QUEUE_SERIAL); //并行队列 self.concurrentQueue = dispatch_queue_create("concurrentQueue.ys.com", DISPATCH_QUEUE_CONCURRENT);
/** 创建异步操作 @param tag 调用本函数时所在的行数 @param concurrent YES 加入到并行队列,NO是加入到串行队列 */ - (void)creatAyOperstionWithTag:(NSInteger)tag concurrent:(BOOL)concurrent { if (concurrent) { //并行队列 dispatch_async(self.concurrentQueue, ^{ NSLog(@"start 任务%ld - %@,",(long)tag,[NSThread currentThread]); sleep(3); NSLog(@"end 任务%ld - %@,",(long)tag,[NSThread currentThread]); }); }else{ //串行队列 dispatch_async(self.serialQueue, ^{ NSLog(@"start 任务%ld - %@,",(long)tag,[NSThread currentThread]); sleep(3); NSLog(@"end 任务%ld - %@,",(long)tag,[NSThread currentThread]); }); } }
/** 创建同步步操作 @param tag 调用本函数时所在的行数 @param concurrent YES 加入到并行队列,NO是加入到串行队列 */ - (void)creatSyOperstionWithTag:(NSInteger)tag concurrent:(BOOL)concurrent { if (concurrent) { //并行队列 dispatch_sync(self.concurrentQueue, ^{ NSLog(@"start 任务所在行数%ld - %@,",(long)tag,[NSThread currentThread]); sleep(3); NSLog(@"end 任务所在行数%ld - %@,",(long)tag,[NSThread currentThread]); }); }else{ //串行队列 dispatch_sync(self.serialQueue, ^{ NSLog(@"start 任务所在行数%ld - %@,",(long)tag,[NSThread currentThread]); sleep(3); NSLog(@"end 任务所在行数%ld - %@,",(long)tag,[NSThread currentThread]); }); } }
//串行队列+同步任务:不会开启新的线程,任务逐步完成。 [self creatSyOperstionWithTag:__LINE__ concurrent:NO]; [self creatSyOperstionWithTag:__LINE__ concurrent:NO]; /* 2018-07-14 13:23:32.502 HaiFeiArrangeProject[142:17113680] start 任务所在行数51 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:23:35.503 HaiFeiArrangeProject[142:17113680] end 任务所在行数51 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:23:35.504 HaiFeiArrangeProject[142:17113680] start 任务所在行数52 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:23:38.505 HaiFeiArrangeProject[142:17113680] end 任务所在行数52 - <NSThread: 0x608000069580>{number = 1, name = main}, */
//串行队列+异步任务:可能开启新的线程,任务逐步完成。 [self creatAyOperstionWithTag:__LINE__ concurrent:NO]; [self creatAyOperstionWithTag:__LINE__ concurrent:NO]; /* 2018-07-14 13:30:39.867 HaiFeiArrangeProject[142:17115945] start 任务56 - <NSThread: 0x608000261200>{number = 5, name = (null)}, 2018-07-14 13:30:42.871 HaiFeiArrangeProject[142:17115945] end 任务56 - <NSThread: 0x608000261200>{number = 5, name = (null)}, 2018-07-14 13:30:42.872 HaiFeiArrangeProject[142:17115945] start 任务57 - <NSThread: 0x608000261200>{number = 5, name = (null)}, 2018-07-14 13:30:45.874 HaiFeiArrangeProject[142:17115945] end 任务57 - <NSThread: 0x608000261200>{number = 5, name = (null)}, */
//并发队列+同步任务:不会开启新的线程,任务逐步完成。 [self creatSyOperstionWithTag:__LINE__ concurrent:YES]; [self creatSyOperstionWithTag:__LINE__ concurrent:YES]; [self creatSyOperstionWithTag:__LINE__ concurrent:YES]; /* 2018-07-14 13:32:29.432 HaiFeiArrangeProject[142:17113680] start 任务所在行数61 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:32:32.434 HaiFeiArrangeProject[142:17113680] end 任务所在行数61 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:32:32.434 HaiFeiArrangeProject[142:17113680] start 任务所在行数62 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:32:35.435 HaiFeiArrangeProject[142:17113680] end 任务所在行数62 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:32:35.435 HaiFeiArrangeProject[142:17113680] start 任务所在行数63 - <NSThread: 0x608000069580>{number = 1, name = main}, 2018-07-14 13:32:38.437 HaiFeiArrangeProject[142:17113680] end 任务所在行数63 - <NSThread: 0x608000069580>{number = 1, name = main}, */
//并发队列+异步任务:开启新的线程,任务同步完成。 [self creatAyOperstionWithTag:__LINE__ concurrent:YES]; [self creatAyOperstionWithTag:__LINE__ concurrent:YES]; [self creatAyOperstionWithTag:__LINE__ concurrent:YES]; /* 2018-07-14 13:33:14.609 HaiFeiArrangeProject[142:17120193] start 任务67 - <NSThread: 0x608000260580>{number = 6, name = (null)}, 2018-07-14 13:33:14.609 HaiFeiArrangeProject[142:17121579] start 任务68 - <NSThread: 0x608000264240>{number = 7, name = (null)}, 2018-07-14 13:33:14.609 HaiFeiArrangeProject[142:17121580] start 任务69 - <NSThread: 0x608000260b00>{number = 8, name = (null)}, 2018-07-14 13:33:17.612 HaiFeiArrangeProject[142:17121580] end 任务69 - <NSThread: 0x608000260b00>{number = 8, name = (null)}, 2018-07-14 13:33:17.612 HaiFeiArrangeProject[142:17120193] end 任务67 - <NSThread: 0x608000260580>{number = 6, name = (null)}, 2018-07-14 13:33:17.612 HaiFeiArrangeProject[142:17121579] end 任务68 - <NSThread: 0x608000264240>{number = 7, name = (null)}, */
----- ----- ----- ----- ------我是分割线----- ----- ----- ------- ----------------我是分割线----- ----- ----
---------------------------------------------我是2019.1.26日更新----- --- ----- ----- ----- ----- ----- -----
关于dispatch的部分函数解释可以参考:dispatch 之 常见函数小结
每周反思:如何使自己的知识系统化,任重道远!
写在结尾处的话:每天努力一点点,也许不明显,但终究会有所帮助!