学习笔记:多线程&GCD

学习笔记:多线程&GCD

多线程基本概念

线程 vs 进程

进程Process:进程是具有一定独立功能的应用程序,是系统进行资源分配和调度的一个独立单位,在内存中有其完备的数据空间和代码空间,一个进程所拥有的数据和变量只属于它自己。
线程Thread:线程是某一进程中一个单独进行的程序。线程是进程的一个实体,是CPU调度和分派的基本单位,是比进程更小的能独立运行的基本单位。线程自己基本不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。
[以上引用自教程]
我的理解是,线程是比进程小的一个程序,能像进程一样独立运行,但由于其并不拥有过多独立的资源而是与其他同属一个进程的线程共享进程所拥有的资源,大概也就是多线程的问题的源头吧。

状态 & 生命周期

状态 : 创建 -> 就绪 -> 运行 -> 阻塞 -> 消亡
生命周期 : 新周期 -> 等待调度 -> 运行 -> 休眠 -> 周期结束

线程安全

由于多个线程可能会访问同一块资源,比如多个线程访问同一个变量,很容易引发数据错乱和数据安全问题,线程安全就是要通过一定机制(线程锁)保证数据的正确性。

串行&并发

由线程安全的含义可知,串行是多个任务排队执行,资源访问是排队进行的,而并行是同一时间多个任务发生,就存在不安全(并行是为了执行效率)

同步&异步

同步是在多任务中,一个任务只能等待另一个任务完成之后才可以进行,而异步的意思是一个任务的执行,不需要等待上一个任务的执行,不会发生堵塞。

atomic(自旋锁)

atomic的作用在于通过给getter和setter加锁,保证锁定的代码在运行中不会被其他调度机制中断(atomic内部有一把自旋锁:判断锁定内容执行完毕后才执行其他操作,会用死循环的方式保证代码执行,下一个线程会一直等待,消耗大量资源,适合不耗时的操作),从而达到线程安全
相反地,有nonatomic,iOS中默认的大部分都是nonatomic的,也就是线程不安全的(所有带有mutable的都是线程不安全的)

synchronized(互斥锁)

与atomic一样能够保证同一时间只有一个线程访问共享资源,保证线程安全
区别在于,互斥锁是如果发现其他线程正在执行锁定的代码,线程会进入休眠状态,等其他的线程执行完毕打开锁之后,线程会去执行

多线程技术

Thread

多线程技术中最轻量级的,需要开发者自己管理线程的生命周期,以及线程之间的同步操作
pthread 是一套通用的多线程的 API,可以在多系统跨平台使用,使用 C 语言编写,需要程序员自己管理线程的生命周期,使用难度较大,在 iOS 开发中几乎不使用 pthread
NSThread 是苹果官方提供的,使用起来比 pthread 更加面向对象,简单易用,可以直接操作线程对象。不过也需要需要程序员自己管理线程的生命周期(主要是创建)

创建

detachThreadSelector(selector:toTarget:with:)
init(target: selector: object:)
performSelector(inBackground: with: ) —-隐式

使用

start() 启动(进入就绪状态)
sleep(1)睡眠
….

GCD

GCD提供的API简单易懂,提供了一个易于使用的并发模型,对于开发者来说,并不需要关心多线程的并发问题,GCD底层自动处理这些逻辑。

通过队列进行GCD操作

队列类型

串行队列(Serial):串行队列的特点是以先进先出的顺序来执行的,队列内的东西是以顺序执行的,但是多个串行队列直接是以并发执行的。
并行队列(Concurrent);并行队列和串行队列相反,可以同时执行多个任务,但是多个任务之间,仍然是以先进先出的顺序执行的,区别在于,并行队列会根据系统负载,尽可能多地创建线程去执行这些任务。但是哪个任务先执行完毕是不确定的。
主线程队列(Main dispatch queue):实际上,主线程队列是一个和主线程相关的串行队列。这个队列中的任务每次只会有一个执行。可以保证所有的任务都会在主线程执行,所以涉及到UI操作的需要使用这个队列来完成。

同步&异步

异步(async):是一个异步添加操作,dispatch_async会立即返回;
同步(sync):是一个同步添加操作,dispatch_sync区别是会阻塞当前线程,会等待block里的任务执行完毕之后才会返回,在当前线程执行,不会开启新线程。

使用方法

创建:Serial/Concurrent
添加到任务队列:async&sync
其他操作:全局并发队列DispatchQueue.global(),QoS优先级,DispatchGroup管理一组任务的执行,DispatchSourceTimer,asyncAfter

NSOperation

NSOpreation基于 GCD 更高一层的封装,比 GCD 更简单易用
操作(Operation):执行操作的意思,换句话说就是你在线程中执行的那段代码。
操作队列(Operation Queues):这里的队列指操作队列,即用来存放操作的队列。NSOperationQueue 对于添加到队列中的操作开始执行顺序(非结束执行顺序)由操作之间相对的优先级决定,操作队列通过设置最大并发操作数来控制并发、串行。
NSOperationQueue 提供了两种不同类型的队列:主队列和自定义队列。主队列运行在主线程之上,而自定义队列在后台执行。

步骤

1.将一个操作封装到NSOperation对象中
2.将NSOperation对象放入NSOperationQueue队列
3.NSOperationQueue自动取出队列中的NSOperation对象放到一条线程中执行

使用

创建队列 :队列分为主队列和自定义队列
将操作加入到队列中:使用 NSOperation 子类创建操作,并使用addOperation /在 block 中添加操作,使用addOperationWithBlock
NSOperationQueue 控制串行执行、并发执行:使用最大并发操作数控制,默认为-1,即不设限,当为1时,即为串行,大于1时,为并发队列

线程间通信

一切UI的操作都需要在主线程上进行,但通常会把一些耗时的操作放在其他线程进行,比如下载图片,所以完成后需要回到主线程,就需要线程间的通信

方法

1.NSThread可以先将自己的当前线程对象注册到某个全局的对象中去,这样相互之间就可以获取对方的线程对象
2.利用GCD达到一个线程传递数据给另一个线程

猜你喜欢

转载自blog.csdn.net/weixin_40477931/article/details/79944399