美文网首页
20、多线程

20、多线程

作者: ChenL | 来源:发表于2020-12-09 10:04 被阅读0次

一、线程、进程的定义

进程
1、 进程 指的是 在系统中 正在运行的一个应用程序
2、每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存空间内
3、通过 活动监听器 可以查看mac系统中所开启的线程

线程
1、线程是进程的基本执行单元,一个进程的所有任务都在线程中进行
2、进程要想执行任务,必须有线程,进行至少要有一条线程
3、程序启动回默认开启主线程/UI线程

可以简单理解:进程为线程的容器,而线程用来执行任务。在iOS中是单进程开发,一个进程就是一个App,进程之间是相互对立的

二、进程与线程的关系

1、地址空间

  • 同一个进程的 线程共享本进程的地址空间
  • 进程之间 则是 独立的地址空间

2、资源拥有

  • 同一个进程内 线程共享本进程的资源,如内存、I/O、CPU等
  • 进程之间的资源是独立的

两者之间的关系就相当于 工厂与流水线的关系,工厂与工厂是相互独立的,而工厂中的流水线是共享工厂的资源,即 进程 相当于一个工厂,线程 相当于一个流水线

注: 进程 & 线程
1、多进程要比多线程健壮
一个进程崩溃后,在保护模式下不会对其他进程产生影响,而一个线程崩溃整个进程就会死掉

2、使用场景:频繁操作、并发操作

进程切换时,消耗的资源大、效率高。所以涉及到频繁的切换 时,使用线程要好于进程。
同样如果要求 同时进行并且又要共享某些变量的并发操作,只能用线程 不能用进程

3、执行过程

每个独立的进程 有一个程序 运行的入口、顺序 执行序列 和 程序入口,但是 线程不能独立执行,必须依赖在应用中,由应用程序提供多个线程执行控制。

4、线程时处理器的基本单位,但进程不是

5、线程没有地址空间,线程包含在进程地址空间中

三、线程与RunLoop的关系

1、runloop 与线程是一一对应的,一个runloop对应一个核心的线程,为什么说是核心的,是因为runloop是可以嵌套的,但是核心的只能由一个,他们的关系保存在一个全局的字典里

2、runloop 是用来管理线程的,当线程的runloop被开启后,线程会在执行完任务后进入休眠状态,有了任务就会被唤醒去执行任务

3、runloop 在第一次获取时被创建,在线程结束时被销毁

4、对于主线程来说, runloop在程序一启动就默认创建好了

5、对于子线程来说,runloop是懒加载的,只是当我们使用的时候才会创建,所以在子线程用定时器要注意:确保子线程的runloop被创建,不然定时器不会回调

四、多线程原理

1、对于单核CPU,同一时间,CPU只能处理一条线程,即只有一条线程在工作

2、iOS 中的多线程同时执行的本质是 CPU在多个任务直接进行快速的切换,由于CPU调度线程的 时间足够快,就造成了 多线程的“同时”执行的效果。其中切换的时间间隔就是时间片

多线程的意义
优点:
1、能适当 提高程序的执行效率,
2、能适当 提高资源的利用率
3、线程上的任务执行完成后,线程会自动销毁

缺点:
1、开启线程需要占用一定的内存空间,默认情况下,每一个线程占用512KB
2、如果开启 大量线程,会占用大量的内存空间,降低程序的性能。
3、线程越多,CPU在调用线程上的开销就会越大
4、程序设计更加复杂,比如线程间的通信,多线程的数据共享

五、多线程的生命周期

image.png

新建:主要是实例化线程对象

就绪:线程对象 调用start方法,将线程对象加入调度线程池,等待CPU的调用 即调用start方法,并不会立即执行,进入就绪状态,需要等待一段时间,经CPU调度后才执行,也就是从就绪状态进入 运行状态

运行:CPU负责调度可调度线程中线程的执行,在线程执行完成之前,其状态可能会在就绪和运行之间来回切换,这个变化是 由CPU负责,开发人员不能干预。

阻塞:当满足某个预定条件时,可以 使用休眠,即sleep,或者同步锁,阻塞线程执行。当进入sleep时,会重新将 线程加入就绪中。下面关于休眠的时间设置,都是NSthread

  • sleepUniteDate:阻塞当前线程,直到指定的时间为止,即 休眠到指定时间
  • sleepForTimeInterval:在给定的时间间隔内休眠线程,即 指定休眠时长
  • 同步锁:@syschronized(self)

死亡:分为两种情况:一、正常死亡:即线程执行完毕;二、非正常死亡:即当满足某个条件后,在线程内部/或者主线中 终止执行 [调用exit方法等退出]

简要说明
处于 运行中的线程 拥有一段可以执行的时间 (时间片)

  • 如果时间片用尽, 线程就会进入 就绪状态队列
  • 如果 时间片没有用尽,且需要开始等待某事件,就会进入阻塞状态队列
  • 等待事件发生之后,线程又会重新进入 就绪状态队列
  • 每当一个线程离开运行,即执行完毕或者强制退出后,会重新 从就绪状态队列 中 选择一个线程继续执行

线程的exit 和 cancel 说明:
exit: 一旦强行终止线程,后续的所有代码都不会执行
cancel :取消当前线程,但是不能取消正在执行的线程

问: 线程的优先级越高,是不是意味着任务的执行越快?

并不是,线程执行的快慢,除了要看优先级,还需要看 资源的大小(任务的复杂度)、以及 CPU调度 情况。在NSThread中,线程优先级threadPriority 已经被服务质量qualityOfService 取代。

六、线程池原理

image.png

第四步 做一下说明:

交给饱和策略去执行,主要有以下四种:
AbortPolicy: 直接抛出RejectedExecutionExeception异常来阻止系统正常运行
CallerRunsPolicy:将任务回退到调用者
DisOldestPolicy:丢掉等待最久的任务
DisCardPolicy:直接丢弃任务

image.png

七、线程安全问题

当多个线程同时访问一块资源时,容易引发数据错乱和数据安全问题,有以下两种解决方案:

  • 互斥锁(同步锁) @synchronized
  • 自旋锁
互斥锁
  • 用于保护临界区,确保 同一时间,只有一条线程能够执行

  • 如果代码中 只有一个地方需要加锁,大多都使用self,这样可以避免单独再创建一个锁对象

  • 加了互斥锁的代码,当新线程访问时,如果发现其他线程正在执行锁定的代码,新线程就会进入休眠

需注意:

  • 互斥锁的锁定范围,应该尽量小,锁定范围越大,效率越差
  • 能够加锁的任意 NSObject对象
  • 锁对象一定要保证所有的线程都能够访问
自旋锁
  • 自旋锁 与 互斥锁 类似,但它不是通过休眠使线程阻塞,而是 在获取锁之前一直处于忙等(原地打转,称为自旋)阻塞状态

  • 使用场景:锁持有的时间短,且线程不希望在重新调度上花太多成本时,就需要使用自旋锁,属性修饰符 atomic,本身就是一把 自旋锁

  • 加入自旋锁,当新线程访问代码时,如果发现有其他线程正在锁定代码,新线程会用 死循环 的方法,一直等待锁定的代码执行完成,即 不停的尝试执行代码,比较消耗性能

区别:
同:

在同一时间,保证了只有一条线程执行任务,即保证了相应同步的功能

不同:

  • 互斥锁:发现其他线程执行,当前线程休眠(就绪状态),进入等待执行,即挂起。一直等待其他线程打开之后,然后唤醒执行

  • 自旋锁:发现其他线程执行,当前线程 一直询问(一直访问),处于忙等状态,耗费的性能比较高

场景:根据任务复杂度区分,使用不同的锁,但判断不全,更多是使用互斥锁去处理;当前任务状态比较 短小时,用自旋锁,反之用互斥锁

八、atomic 原子锁 & nonatomic 非原子锁

atomic 和 nonatomic 主要用于属性的修饰

atomic 是原子属性,是为了 多线程开发准备的,是默认属性

  • 仅仅在属性的 setter 方法中,增加了锁( 自旋锁),能够保证同一时间,只有一条线程 对属性进行写操作
  • 同一时间 单(线程)写多(线程)读的线程处理技术 (Mac 常用)

nonatomic :非原子属性

  • 没有锁、性能高!
    (移动端开发常用)

相关文章

  • 20、多线程

    一、线程、进程的定义 进程1、 进程 指的是 在系统中 正在运行的一个应用程序2、每个进程之间是独立的,每个进程均...

  • 马士兵java最全学习资源,赶紧收藏一下

    马士兵2020年最新Java多线程高并发讲解——20年架构师告诉你Java多线程与高并发应该怎么学 https:/...

  • 马士兵java最全学习资源,赶紧收藏一下

    马士兵2020年最新Java多线程高并发讲解——20年架构师告诉你Java多线程与高并发应该怎么学 https:/...

  • day 20 多线程

    一、多线程 每个程序在运行的时候(进程)系统都会为这个进程创建一个线程,这个线程我们叫主线程。程序员自己创建的线程...

  • 20.多线程

    有了GCD为什么还要用NSOperationQueue GCD是底层的C语言构成的API,而NSOperation...

  • 20总 多线程

    1.复习: 2.多线程: 每个程序在运行的时候(进程)系统都会为这个进程创建一个线程,这个线程我们叫主线程。程序员...

  • 20 Python多线程

    多线程编程技术可以实现代码并行,优化处理能力,同时可以将代码划分为功能更小的模块,使代码的可重用性更好。这里将介绍...

  • 笔记-多线程

    2017/02/20今天的目标只有一个:弄懂多线程(真心的) 一、认识多线程 进程: 在系统中正在运行的一个应用程...

  • Python的并行--threading和mutiprocess

    一、多线程计算试验 分别计算5,10,20的阶乘和,运行结果都在2s左右,速度比不用多线程快很多,甚至可以开到10...

  • 马士兵2020年最新Java多线程与高并发

    马士兵2020年最新Java多线程与高并发讲解——20年架构师告诉你Java多线程与高并发应该怎么学_哔哩哔哩 (...

网友评论

      本文标题:20、多线程

      本文链接:https://www.haomeiwen.com/subject/tntviktx.html