iOS多线程开发之深入GCD 一、前言 在以前的一些系列博客中,对iOS中线程的管理做了总结,其中涵盖了GCD的相关基础知识:http://my.oschina.net/u/2340880 那里面将GCD的线程管理能力,列队组能力,通过信号和消息控制程序流程的能力都有介绍,这里,我们继续深入GCD的功能,通过GCD来处理一些逻辑更加复杂的代码功能。 )aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; 然而,如果我们需要在多线程中进行延时操作,上面两种方式会显得十分麻烦 三、数据存取的线程安全问题 在进行多线程编程时,或许总会遇到一类问题,数据的竞争与线程的安全。这些问题如果我们通过程序手动来控制难度将会非常大。 ,可是并不能保证程序百分百的安全,因为在多线程的操作中,会有可能初始化多个对象,在GCD中,我们可以使用如下方式: +(instancetype)shared{ static Auto * obj
多线程经典问题:资源共享 ? 代码实现: ? 形成一条资源的bug ? 解决方案 ? 互斥锁小结 保证锁内的代码,同一时间,只有一条线程能够执行! 互斥锁参数 能够加锁的任意 NSObject 对象 注意:锁对象一定要保证所有的线程都能够访问 如果代码中只有一个地方需要加锁,大多都使用 self,这样可以避免单独再创建一个锁对象 说到锁,我们再来看看苹果爸爸的给出干货 atomic与nonatomic 的区别 nonatomic 非原子属性 atomic 原子属性(线程安全),针对多线程设计的,默认值 保证同一时间只有一个线程能够写入(但是同一个时间多个线程都可以取值 ) atomic 本身就有一把锁(自旋锁) 单写多读:单个线程写入,多个线程可以读取 atomic:线程安全,需要消耗大量的资源 nonatomic:非线程安全,适合内存小的移动设备 iOS 开发的建议 所有属性都声明为 nonatomic 尽量避免多线程抢夺同一块资源 尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力 这是多线程系列的第三篇文章,下篇会继续探究多线程, 敬请期待.
Vite学习指南,基于腾讯云Webify部署项目。
“ 多线程,作为实现软件并发执行的一个重要的方法,也开始具有越来越重要的地位!” ? 正式因为多线程能够在时间片里被CPU快速切换,造就了以下优势 资源利用率更好 程序设计在某些情况下更简单 程序响应更快 但是并不是非常完美,因为多线程常常伴有资源抢夺的问题,作为一个高级开发人员并发编程那是必须要的 换句话说:使用条件变量可以让许多线程一起等待某个时间的发生,当某个时间发生时,所有的线程可以一起恢复执行! r_sem); 读读读…… sem_wait(&r_sem); readers- -; if(readers == 0) sem_post(&w_sem); sem_post(&r_sem); 线程的安全是现在各个领域在多线程开发必须要掌握的基础 只有对底层有所掌握,才能在真正的实际开发中游刃有余!现在的iOS开发乃至其他开发都是表面基础层开发,真正大牛开发之路还请继续努力,这一篇博客以供大家一起学习!
多线程,作为实现软件并发执行的一个重要的方法,也开始具有越来越重要的地位! [1240] 正式因为多线程能够在时间片里被CPU快速切换,造就了以下优势 资源利用率更好 程序设计在某些情况下更简单 程序响应更快 但是并不是非常完美,因为多线程常常伴有资源抢夺的问题,作为一个高级开发人员并发编程那是必须要的 换句话说:使用条件变量可以让许多线程一起等待某个时间的发生,当某个时间发生时,所有的线程可以一起恢复执行! 读读读…… sem_wait(&r_sem); readers- -; if(readers == 0) sem_post(&w_sem); sem_post(&r_sem); 复制代码 线程的安全是现在各个领域在多线程开发必须要掌握的基础 只有对底层有所掌握,才能在真正的实际开发中游刃有余!现在的iOS开发乃至其他开发都是表面基础层开发,真正大牛开发之路还请继续努力,这一篇博客以供大家一起学习!
本文重点 NSThread 多线程基础、pthread、开启线程的3种方式 线程的状态、线程安全问题、线程间的通信 GCD 同步方法和异步方法、队列的使用、线程间的通信 延迟执行、一次性代码、队列组 多线程并发执行,其实就是CPU快速地在多条线程之间调度(如果CPU调度的时间足够快,就造成了多线程并发执行的假象) 二、多线程在iOS开发中的应用 1、什么是主线程:一个iOS程序运行之后,默认会开启一条线程 2.2 iOS中多线程的实现方案 公众号:iOS逆向 iOS支持多个层次的多线程编程,层次越高的抽象程度越高,使用也越方便,也是苹果最推荐使用的方法。 根据抽象层次从低到高依次列出iOS所支持的多线程编程方法: Thread :是三种方法里面相对轻量级的,但需要管理线程的生命周期、同步、加锁问题,这会导致一定的性能开销 Cocoa Operations Grand Central Dispatch(简称GCD,iOS4开始支持):提供了一些新特性、运行库来支持多核并行编程,它的关注点更高:如何在多个cpu上提升效率 2.4 线程状态 公众号:iOS逆向
在前面的博客中如果用到了异步请求的话,也是用到的第三方的东西,没有正儿八经的用过iOS中多线程的东西。 其实多线程的东西还是蛮重要的,如果对于之前学过操作系统的小伙伴来说,理解多线程的东西还是比较容易的,今天就做一个小的demo来详细的了解一下iOS中的多线程的东西。 三、线程间的同步问题(为我们的线程添加上同步锁) 在操作系统中讲多线程时有一个名词叫脏数据,就是多个线程操作同一块资源造成的,下面就修改一下代码,让数据出现问题,然后用同步锁来解决这个问题 GCD的串行队列开始执行的顺序如下,下面是是在一个线程中按FIFO的顺序执行的: ? GCD中的并行队列,是在不同的线程中同时执行的: ? 今天博客中的内容还是蛮多的,如果之前接触过Java的多线程的东西,或者其他语言中的多线程的话,理解起来应该问题不大。
四、多线程 1个进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务。进程 -> 车间,线程 -> 车间工人。多线程技术可以提高程序的执行效率。 比如可以同时下载多个文件。 多线程并发(同时)执行,其实是 CPU 快速地在多条线程之间调度(切换),如果 CPU 调度的时间够快,就造成了多线程并发执行的假象。 但是如果线程非常非常多,会发生什么情况呢? 六、多线程的优缺点 优点: 能适当提高程序的执行效率 能适当提高资源利用率(CPU、内存利用率) 缺点: 创建线程是有开销的,iOS下主要成本包括:内核数据结构(大约 1 KB)、栈空间(子线程 512 如果开启大量的线程,会降低程序的性能 线程越多,CPU 在调度线程上的开销越大 *程序设计更加复杂:比如线程之间的通信,多线程的数据共享。 七、多线程在 iOS 开发中的应用 主线程:一个 iOS 程序运行后,默认会开启一条线程,称为『主线程』或『UI 线程』。
一·什么是线程,进程 打开我们的管理控制器 QQ截图20201214000219.png 二·五大区 栈 局部变量&调用的上下文 (自动管理,可读可写,不可执行) 函数的参数:id,self,sel, imp 堆 new&malloc (手动管理,可读可写,不可执行) 开辟空间alloc,并且赋予一个地址指针,方便管理,通过链表结构(方便增删,不便查找)所以通过类似数组的形式,给开辟的空间一个指针地址 常量区(已初始化区) 字符串 & 常量 &宏定义 (只读,不可执行) 全局区(未初始化区) 静态变量&全局变量(可读可写,不可执行) 代码区 __TEXT(指令,只读,可执行) 三·线程生命周期 QQ 截图20201214003012.png 四·线程池工作大概原理 QQ截图20201214003634.png 五·饱和策略(AbortPolicy) 1.RejectedExecutionExeception 资源抢夺 当我们讨论线程安全,问题都会归于一个问题上:在I/O操作中,在线程与线程之间会发生资源抢夺 应对方法:1.加锁 synchronized 互斥锁:进入runable状态,等待唤醒 自旋锁:一直访问
[1240] 收录:原文地址 写在前面 多线程技术在移动端开发中应用广泛,GCD 让 iOS 开发者能轻易的使用多线程,然而这并不意味着代码就一定高效和可靠。 不管是多处理器设备还是多核设备,开发者往往只需要关心 CPU 的核心数量,而不需关心它们的物理构成。 二、多线程的优化思路 在移动端开发中,因为系统的复杂性,开发者往往不能期望所有线程都能真正的并发执行,而且开发者也不清楚 XNU 何时切换内核态线程、何时进行线程调度,所以开发者要经常考虑到线程调度的情况 虽然内核态线程的切换理论上不会是性能负担,开发中还是应该尽量减少线程的切换。 4、时刻注意不可重入方法的安全 当一个方法是可重入的时候,可以放心大胆的使用,若一个方法不可重入,开发者应该多留意,思考这个方法会不会有多个线程访问的情况,若有就老老实实的加上线程锁。
线程的优点 因为要并发,我们发明了进程,又进一步发明了线程。只不过进程和线程的并发层次不同:进程属于在处理器这一层上提供的抽象;线程则属于在进程这个层次上再提供了一层并发的抽象。 除了提高进程的并发度,线程还有个好处,就是可以有效地利用多处理器和多核计算机。现在的处理器有个趋势就是朝着多核方向发展,在没有线程之前,多核并不能让一个进程的执行速度提高,原因还是上面所有的两点限制。 但如果讲一个进程分解为若干个线程,则可以让不同的线程运行在不同的核上,从而提高了进程的执行速度。 例如:我们经常使用微软的Word进行文字排版,实际上就打开了多个线程。 一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 for i in range(20): name = '小喻%d' %(i,) temp = consumer(name,que) temp.start() python 多线程开发之事件
OS X和iOS的核心XNU内核在发生操作系统事件时(如每隔一定时间,唤起系统调用等情况)会切换执行路径。 串行:一个线程按顺序执行 并发:由于使用多线程的程序可以在某个线程和其他线程之间反复多次进行上下文切换,因此看上去就好像1个CPU核能够并列的执行多个线程一样。 假设准备4个Concurrent Dispatch Queue 用线程。首先blk0在线程0中开始执行,接着blk1在线程1中、blk2在线程2中、blk3在线程3中开始执行。 线程0中blk0执行结束后开始执行blk4,由于线程1中blk1的执行没有结束,因此线程2中blk2执行结束后开始执行blk5,就这样循环往复。 关于使用NSOperation进行多线程编程,看我这篇帖子:iOS多线程--NSOperation demo下载:https://github.com/wangdachui/multithreading.git
selector: selector(ViewController.threadAction), object:nil) 2 thread.stackSize = 1024 * 1024 ///使用线程下载图片 imageView = UIImageView() 2 var label = UILabel() 接着对viewDidLoad方法进行修改,对imageView属性和label属性进 行初始化,并创建一个新的线程来执行网络图片的下载工作
)ti; //进入阻塞状态 强制停止线程 +(void)exit; //进入死亡状态 注意:一旦线程停止(死亡)了,就不能再次开启任务。 五、多线程的安全隐患 资源共享 1 块资源可能会被多个线程共享,也就是说多个线程可能会访问同一块资源 比如多个线程访问同一个对象、同一个变量、同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题 缺点:需要消耗大量的 CPU 资源 3.互斥锁的使用前提:多条线程抢夺同一块资源 4.相关专业术语:线程同步 线程同步的意思是:多条线程在同一条线上执行(按顺序地执行任务) 互斥锁,就是使用了线程同步技术 ,需要消耗大量的资源 nonatomic:非线程安全,适合内存小的移动设备 iOS开发建议 所有属性都声明为 nonatomic 尽量避免多线程抢夺同一资源 尽量将加锁,资源抢夺的业务逻辑交给服务器端处理 在一个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 2.线程间通信的体现 1 个线程传递数据给另一个线程 在 1 个线程中执行完特定任务后,转到另 1 个线程继续执行任务 3.线程间通信常用方法
配合使用 NSOperation 和 NSOperationQueue 也能实现多线程编程。 NSOperation 和 NSOperationQueue 实现多线程的具体步骤 先将需要执行的操作封装到一个 NSOpertion 对象中 然后将 NSOperation 对象添加到 NSOperationQueue -(void)start; 一旦执行操作,就会调用 target 的 sel 方法 注意: 默认情况下,调用了 start 方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作 只有将 同时执行的任务数,比如,同时开 3 个线程执行 3 个任务,并发数就是 3 最大并发数的相关方法 -(NSInteger)maxConcurrentOperationCount; -(void)setMaxConcurrentOperationCount 非主队列(其他队列) [[NSOperationQueue alloc] init] 同时包含了:串行、并发功能 添加到这种队列中的任务(NSOperation),就会自动放到子线程中执行 8.NSOperation
一、GCD 的优势 GCD 是苹果公司为多核的并行运算提出的解决方案 GCD 会自动利用更多的 CPU 内核(比如双核,四核)* GCD 会自动管理线程的生命周期(创建线程,调度任务,销毁线程) 程序只需要告诉 ,不具备开启新线程的能力 异步:可以在新的线程中执行任务,具备开启新线程的能力 四、队列的类型 GCD 的队列可以分为 2 大类型 并发队列(Concurrent Dispatch Queue) 可以让多个任务并发 (同时)执行(自动开启多个线程同时执行任务) 并发功能只有在异步(dispatch_async)函数下才有效 串行队列(Serial Dispatch Queue) 让任务一个接着一个地执行(一个任务执行完毕后 ,再执行下一个任务) 五、容易混淆的术语 同步和异步主要影响:能不能开启新的线程 同步:只是在当前线程中执行任务,不具备开启新线程的能力 异步:可以在新的线程中执行任务,具备开启新线程的能力 并发和串行主要影响 :任务的执行方式 并发:允许多个任务并发(同时)执行 串行:一个任务执行完毕后,再执行下一个任务 六、并发队列 //创建一个并发队列 // label :相当于队列的名字 dispatch_queue_t
在GCD多线程的学习中,我发现了dispatch_set_target_queue这个函数。 如果您将一个块提交给一个串行队列,而串行队列的目标队列是一个不同的串行队列,那么该块不会与提交给目标队列或具有相同目标队列的任何其他队列的块并发调用。 17.384964+0800 Target[95606:2398989] 2 2019-03-26 11:37:17.385006+0800 Target[95606:2398995] 4 也就是乱序,并发执行的 我们在实际开发中可以使用这种技术避免并发执行。 注:若将目标队列targetQueue修改为并发队列,则不会有什么实际的效果,还是并发执行 dispatch_queue_t targetQueue = dispatch_queue_create("serial
之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread、操作队列以及GCD,介绍的不够深入。今天就以GCD为主题来全面的总结一下GCD的使用方式。 GCD在iOS开发中还是比较重要的,使用场景也是非常多的,处理一些比较耗时的任务时基本上都会使用到GCD, 在使用是我们也要主要一些线程安全也死锁的东西。 其实并行队列与异步执行方式相结合才能大大的提供效率,因为使用异步执行并行队列时会开辟多个线程来同时执行并行队列中的任务。 下方就是延迟执行的的代码,因为改代码输出结果比较简单,在此就不做过多的赘述了。需要注意的是延迟执行会在新开辟的队列中进行执行,不会阻塞新的线程。 ? 如果你使用dispatch_apply()函数来执行并行队列,虽然会开启多个线程来循环执行并行队列中的任务,但是仍然会阻塞当前线程。
Python的线程开发使用标准库threading Thread类 def __init__(self,group=None,target=None,name=None,args(),kwargs=None enumerate( ) 返回所有活着的线程的列表,不包括已经终止的线程和未开始的线程 get_ident( ) 返回当前线程的ID,非0整数 import threading import getName(),setName()获取,设置这个名词 ident 线程ID,它是非0整数,线程启动后才会有ID,线程退出,仍可以访问,可重复使用 is_alive() 返回线程是否存活 多线程 一个进程中如果有多个线程 ,就是多线程,实现一种并发 import threading import time def worker(): count=0 while True: if(count 一个线程可以被join多次,timeout是设置等待调用者多久,如果没有设置,就一直等待,直到被调用者线程结束。
缺点 开启线程需要占用一定的内存空间,如果开启大量的线程,会占用大量的内存空间,降低程序的性能。 线程越多,CPU 在调度时开销就越大。 多线程编程 iOS 中的多线程技术主要分为 3 种,分别为 Thread、GCD 和 Operation。 Thread 面向对象。 需要手动创建线程,但不需要手动销毁。 并发队列在执行多个任务的时候,会开辟多个线程执行。而串行队列不会,它会执行完一个再去执行另外一个。 默认会开启多少个线程执行任务。 有两个重要的概念: 临界资源:一次只能允许一个线程使用的共享资源。 临界区:访问临界资源的那段代码。 在实际开发中,经常存在多个线程访问同一个共享资源的情况,那么如何保证多线程执行结果的正确性?
云开发(Tencent Cloud Base,TCB)是腾讯云为移动开发者提供的一站式后端云服务,支持小程序、小游戏、Web、APP开发。它帮助开发者统一构建和管理资源,让开发者可以专注于业务逻辑的实现,而无需理解后端逻辑及服务器运维知识,开发门槛更低,效率更高。
扫码关注云+社区
领取腾讯云代金券