iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >iOS 如何高效的使用多线程
  • 589
分享到

iOS 如何高效的使用多线程

ios高效多线程 2022-05-25 10:05:42 589人浏览 独家记忆
摘要

一、多线程简述 线程是程序执行流的最小单元,一个线程包括:独有ID,程序计数器 (Program Counter),寄存器集合,堆栈。同一进程可以有多个线程,它们共享进程的全局变量和

一、多线程简述

线程是程序执行流的最小单元,一个线程包括:独有ID,程序计数器 (Program Counter),寄存器集合,堆栈。同一进程可以有多个线程,它们共享进程的全局变量和堆数据。

这里的 PC (Program Counter) 指向的是当前的指令地址,通过 PC 的更新来运行我们的程序,一个线程同一时刻只能执行一条指令。当然我们知道线程和进程都是虚拟的概念,实际上 PC 是 CPU 核心中的寄存器,它是实际存在的,所以也可以说一个 CPU 核心同一时刻只能执行一个线程。

不管是多处理器设备还是多核设备,开发者往往只需要关心 CPU 的核心数量,而不需关心它们的物理构成。CPU 核心数量是有限的,也就是说一个设备并发执行的线程数量是有限的,当线程数量超过 CPU 核心数量时,一个 CPU 核心往往就要处理多个线程,这个行为叫做线程调度。

线程调度简单来说就是:一个 CPU 核心轮流让各个线程分别执行一段时间。当然这中间还包含着复杂的逻辑,后文再来分析。

二、多线程的优化思路

在移动端开发中,因为系统的复杂性,开发者往往不能期望所有线程都能真正的并发执行,而且开发者也不清楚 XNU 何时切换内核态线程、何时进行线程调度,所以开发者要经常考虑到线程调度的情况。

1、减少线程切换

当线程数量超过 CPU 核心数量,CPU 核心通过线程调度切换用户态线程,意味着有上下文的转换(寄存器数据、栈等),过多的上下文切换会带来资源开销。虽然内核态线程的切换理论上不会是性能负担,开发中还是应该尽量减少线程的切换。

2、线程优先级权衡

通常来说,线程调度除了轮转法以外,还有优先级调度的方案,在线程调度时,高优先级的线程会更早的执行。有两个概念需要明确:

  • io 密集型线程:频繁等待的线程,等待的时候会让出时间片。
  • CPU 密集型线程:很少等待的线程,意味着长时间占用着 CPU。

特殊场景下,当多个 CPU 密集型线程霸占了所有 CPU 资源,而它们的优先级都比较高,而此时优先级较低的 IO 密集型线程将持续等待,产生线程饿死的现象。当然,为了避免线程饿死,系统会逐步提高被“冷落”线程的优先级,IO 密集型线程通常情况下比 CPU 密集型线程更容易获取到优先级提升。

虽然系统会自动做这些事情,但是这总归会造成时间等待,可能会影响用户体验。所以笔者认为开发者需要从两个方面权衡优先级问题:

  • 让 IO 密集型线程优先级高于 CPU 密集型线程。
  • 让紧急的任务拥有更高的优先级。

比如一个场景:大量的图片异步解压的任务,解压的图片不需要立即反馈给用户,同时又有大量的异步查询磁盘缓存的任务,而查询磁盘缓存任务完成过后需要反馈给用户。

图片解压属于 CPU 密集型线程,查询磁盘缓存属于 IO 密集型线程,而后者需要反馈给用户更加紧急,所以应该让图片解压线程的优先级低一点,查询磁盘缓存的线程优先级高一点。

值得注意的是,这里是说大量的异步任务,意味着 CPU 很有可能满负荷运算,若 CPU 资源绰绰有余的情况下就没那个必要去处理优先级问题。

3、主线程任务的优化

有些业务只能写在主线程,比如 UI 类组件的初始化及其布局。其实这方面的优化就比较多了,业界所说的性能优化大部分都是为了减轻主线程的压力,似乎有些偏离了多线程优化的范畴了,下面就基于主线程任务的管理大致罗列几点吧:

  • 内存复用

通过内存复用来减少开辟内存的时间消耗,这在系统 UI 类组件中应用广泛,比如 UITableViewCell 的复用。同时,减少开辟内存意味着减少了内存释放,同样能节约 CPU 资源。

  • 懒加载任务

既然 UI 组件必须在主线程初始化,那么就需要用时再初始化吧,swift 的写时复制也是类似的思路。

  • 任务拆分排队执行

通过监听 Runloop 即将结束等通知,将大量的任务拆分开来,在每次 Runloop 循环周期执行少量任务。其实在实践这种优化思路之前,应该想想能不能将任务放到异步线程,而不是用这种比较极端的优化手段。

  • 主线程空闲时执行任务

//这里是主线程上下文

`dispatch_async(dispatch_get_main_queue(), ^{

//等到主线程空闲执行该任务

});

三、关于“锁”

多线程会带来线程安全问题,当原子操作不能满足业务时,往往需要使用各种“”来保证内存的读写安全。

常用的锁有互斥锁、读写锁、空转锁,通常情况下,iOS 开发中互斥锁pthread_mutex_t、dispatch_semaphore_t,读写锁pthread_rwlock_t就能满足大部分需求,并且性能不错。

在读取锁失败时,线程有可能有两种状态:

  • 空转状态:线程执行空任务循环等待,当锁可用时立即获取锁。
  • 挂起状态:线程挂起,当锁可用时需要其他线程唤醒。

唤醒线程比较耗时,线程空转需要消耗 CPU 资源并且时间越长消耗越多,由此可知空转适合少量任务、挂起适合大量任务。

实际上互斥锁和读写锁都有空转锁的特性,它们在获取锁失败时会先空转一段时间,然后才会挂起,而空转锁也不会永远的空转,在特定的空转时间过后仍然会挂起,所以通常情况下不用刻意去使用空转锁,Casa Taloyum 在博客中有详细的解释。

1、OSSpinLock 优先级反转问题

优先级反转概念:比如两个线程 A 和 B,优先级 A < B。当 A 获取锁访问共享资源时,B 尝试获取锁,那么 B 就会进入忙等状态,忙等时间越长对 CPU 资源的占用越大;而由于 A 的优先级低于 B,A 无法与高优先级的线程争夺 CPU 资源,从而导致任务迟迟完成不了。解决优先级反转的方法有“优先级天花板”和“优先级继承”,它们的核心操作都是提升当前正在访问共享资源的线程的优先级。

2、避免死锁

很常见的场景是,同一线程重复获取锁导致的死锁,这种情况可以使用递归锁来处理,pthread_mutex_t使用pthread_mutex_init_recursive()方法初始化就能拥有递归锁的特性。

使用pthread_mutex_trylock()等尝试获取锁的方法能有效的避免死锁的情况

3、最小化加锁任务

开发者应该充分的理解业务,将锁包含的代码区域尽量缩小,不会出现线程安全问题 的代码就不要用锁来保护了,这样才能提高并发时锁的性能。

4、时刻注意不可重入方法的安全

当一个方法是可重入的时候,可以放心大胆的使用,若一个方法不可重入,开发者应该多留意,思考这个方法会不会有多个线程访问的情况,若有就老老实实的加上线程锁。

5、编译器的过度优化

编译器可能会为了提高效率将变量写入寄存器而暂时不写回,方便下次使用,我们知道一句代码转换为指令不止一条,所以在变量写入寄存器没来得及写回的过程中,可能这个变量被其它线程读写了。编译器同样会为了提高效率对它认为顺序无关的指令调换顺序。

以上都可能会导致合理使用锁的地方仍然线程不安全,而volatile关键字就可以解决这类问题,它能阻止编译器为了效率将变量缓存到寄存器而不及时写回,也能阻止编译器调整操作volatile修饰变量的指令顺序。

原子自增函数就有类似的应用: int32_t OSAtomicIncrement32( volatile int32_t *__theValue )

CPU 也可能为了提高效率而去交换指令的顺序,导致加锁的代码也不安全,解决这类问题可以使用内存屏障,CPU 越过内存屏障后会刷新寄存器对变量的分配。

以上就是iOS 如何高效使用的多线程的详细内容,更多关于ios 多线程的资料请关注编程网其它相关文章!

--结束END--

本文标题: iOS 如何高效的使用多线程

本文链接: https://www.lsjlt.com/news/30432.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何用 Java 同步在 IDE 中实现高效的多线程编程?
    Java 是一种广泛使用的编程语言,尤其在多线程编程方面有着广泛的应用。在多线程编程中,同步是一种非常重要的机制,可以确保多个线程之间的数据共享和协调。本文将介绍如何使用 Java 同步在 IDE 中实现高效的多线程编程。 一、同步机制的...
    99+
    2023-06-26
    同步 ide http
  • 使用SDLocalize实现高效完成iOS多语言工作
    SDLocalize 该方案最大特点是对旧代码几乎没有较多修改就可以完成从单语言项目修改为多语言的项目。并支持XIB的控件本地化,无需创建不同语言版本的XIB文件。 SDLocali...
    99+
    2022-11-13
    IOS多国语言Localize方法 iOS 项目多语言配置 SDLocalize的使用
  • Python多线程如何使用
    今天小编给大家分享一下Python多线程如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一,实用方法线程之间执行是无序...
    99+
    2023-06-29
  • iOS中多线程的示例分析
    这篇文章给大家分享的是有关iOS中多线程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、iOS的三种多线程技术NSThread–优点:NSThread 比其他两个轻量级,使用简单–缺点:需要自己管理线...
    99+
    2023-06-21
  • 如何使用iOS实现仿高德首页推拉效果
    这篇文章主要介绍了如何使用iOS实现仿高德首页推拉效果,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。上面是实现的效果,滑动的视图是新建的一个UIView子类1、滑动view的...
    99+
    2023-06-25
  • 如何使用Python中的多线程编程
    如何使用Python中的多线程编程,需要具体代码示例引言:随着计算机技术的不断发展,多核处理器的普及以及大数据时代的到来,多线程编程变得越来越重要。多线程编程可以充分利用计算机的多个核心,加快程序的执行速度,提高系统的响应性能。Python...
    99+
    2023-10-22
    Python多线程编程
  • Java多线程编程如何使用
    本篇内容主要讲解“Java多线程编程如何使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java多线程编程如何使用”吧!Process和Thread程序是指令和数据的有序集合, 本身没有运行的...
    99+
    2023-06-22
  • 如何使用多线程和锁
    本篇内容介绍了“如何使用多线程和锁”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、前言你只面向工作学习吗...
    99+
    2024-04-02
  • C#多线程使用Parallel.ForEach并行循环,真的能提高效能
    是的,使用Parallel.ForEach可以提高程序的执行效率。Parallel.ForEach方法可以将一个集合分成多个小块,并...
    99+
    2023-09-23
    C#
  • C#中如何使用多线程编程提高并发性能
    C#中如何使用多线程编程提高并发性能随着计算机技术的飞速发展,现代软件系统对于并发性能的需求也越来越高。尤其是在处理大量并发请求、并行计算以及IO密集型操作时,单线程往往无法充分利用CPU和其他系统资源,导致性能瓶颈和响应时间延长。而使用多...
    99+
    2023-10-22
    并发性能 C#多线程编程
  • 高效利用Golang的多线程编程:实践与技巧
    Golang多线程编程的最佳实践与技巧 引言:随着计算机硬件能力的不断提升,多线程编程已成为现代软件开发中的重要技术。Golang作为一门并发性能极佳的编程语言,充分利用多核处理器的能力,使得多线程编程更加简...
    99+
    2024-01-20
    多线程 Golang 最佳实践
  • C#如何使用多线程中的lock
    小编给大家分享一下C#如何使用多线程中的lock,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!经常碰到同时需要对某个数据进行操作,或者对某个文件进行读写操作,对于...
    99+
    2023-06-17
  • 浅谈多线程_让程序更高效的运行
    Java Thread 的一些认识:Java是抢占式线程,一个线程就是进程中单一的顺序控制流,单个进程可以拥有多个并发任务,其底层是切分CPU时间,多线程和多任务往往是使用多处理器系统的最合理方式进程可以看作一个程序或者一个应用;线程是进程...
    99+
    2023-05-31
    多线程 更高
  • C#多线程编程Task如何使用
    这篇“C#多线程编程Task如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C#多线程编程Task如何使用”文章吧。一...
    99+
    2023-06-29
  • 《PHP并发编程技巧:使用容器实现高效的多线程操作》?
    PHP并发编程技巧:使用容器实现高效的多线程操作 随着Web应用程序的不断发展,多线程编程成为了PHP开发人员日常工作中的一个重要部分。使用多线程技术可以显著提高应用程序的性能和响应速度。但是,多线程编程也带来了一些挑战,例如线程同步、死锁...
    99+
    2023-10-02
    并发 教程 容器
  • Java多线程Thread类如何使用
    这篇文章主要讲解了“Java多线程Thread类如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java多线程Thread类如何使用”吧!Thread类的基本用法创建子类,继承自Thr...
    99+
    2023-07-02
  • 如何在 Python 中使用多线程和多进程来提高并发性能?
    在编写 Python 程序时,我们通常会遇到需要同时处理多个任务的情况,如何有效地提高程序的并发性能是一个非常重要的问题。Python 中的多线程和多进程技术是两种常见的解决方案,本文将介绍如何使用这两种技术来提高程序的并发性能。 一、多线...
    99+
    2023-09-26
    并发 spring 自然语言处理
  • 锁如何在多线程中使用
    本篇文章为大家展示了锁如何在多线程中使用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、ReentrantLockpackage com.ietree.basicskill.mutilthread...
    99+
    2023-05-31
    多线程
  • 如何高效的使用Response.Redirect
    要高效地使用Response.Redirect,可以遵循以下几个步骤:1. 确保在重定向之前完成所有必要的处理和验证。这样可以避免在...
    99+
    2023-08-09
    Response.Redirect
  • 《PHP容器并发编程实践:如何实现高效的多线程并发?》
    PHP容器并发编程实践:如何实现高效的多线程并发? 在如今的互联网时代,高并发已经成为了一个家喻户晓的话题。而对于PHP开发者来说,如何实现高效的多线程并发则成为了一个必须掌握的技能。本文将介绍PHP容器并发编程的实践方法,帮助开发者实现高...
    99+
    2023-10-02
    并发 教程 容器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作