多线程基础

来源:互联网 发布:画平面图的软件 编辑:程序博客网 时间:2024/06/11 11:23
多线程基础
计算机在处理循环的时候,速度非常快。
栈区内存读取速度很快。
堆区读取的速度比栈区慢。
io设备速度特别慢。

同步执行:由上到下,由左到右。一个接一个执行。
异步执行:多个人可以同时执行多个任务。

进程:是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存空间内。

线程:是进程的基本执行单元,一个进程的所有任务都在线程中执行。 
多线程可以提高程序的执行效率。


 (单核CPU)同一时间,cpu只能处理1个线程,只有1个线程在执行 
多线程同时执行:是CPU快速的在多个线程之间的切换
 cpu调度线程的时间足够快,就造成了多线程的“同时”执行
如果线程数非常多,cpu会在n个线程之间切换,消耗大量的cpu资源 
每个线程被调度的次数会降低,线程的执行效率降低


主线程:一个程序运行后,默认会开启1个线程,称为“主线程”或“UI线程”
主线程一般用来 刷新UI界面 ,处理UI事件(比如:点击、滚动、拖拽等事件) 
主线程使用注意 别将耗时的操作放到主线程中耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种卡的坏体验 。


多线程:切换执行,切换速度很快,“同时执行”
优点:提高了程序的执行效率
缺点: 线程并不是开的越多越好
占用过多的cpu 内存资源(默认情况下,每一个线程都占512KB),导致系统运行缓慢
 程序复杂,线程间的通信 、共享资源的出现问题


iOS中多线程的实现方案:

1.pthread(跨平台):POSIX 可移植  C语言 线程生命周期需要管理(了解)

2.NSthread: OC   线程生命周期需要管理
1.对象方法
2.类方法detach
3.隐式 

3.CGD: C 线程生命周期不需要管理 使用频率高, 给我们做了多核CPU的优化。

4.NSOperation: OC  线程生命周期不需要管理 使用频率高。(基于GCD的封装,底层是GCD)

bridge:在ARC中,使用到和c语言对应的数据类型,应该使用__bridge 桥接     
在MRC中,不需要桥接          
在OC中,如果是ARC的话,编译的时候会自动添加 retain、release、autorelease     
ARC只负责OC的代码,不负责c的代码     
如果c语言的框架 中,函数名中出现create、retain、copy,需要release    
桥接的目的就是解决上述问题

线程生命周期:
1.新建
2.就绪 start  (就绪,在可调度线程池,等CPU)
3.运行
4.堵塞  
  • sleepForTimeInterval:休眠指定时长
  • sleepUntilDate:休眠到指定日期
  • @synchronized(self):乎斥锁
5.死亡
强制停止线程  + (void)exit;


线程的状态:
name 给线程设定名字

threadPriority  优先级,优先级高的不一定比优先级低的先运行,有更多可能性被cpu调度            
0.0~1.0 默认0.5

判断是否是主线程

主线程相关用法
+ (NSThread *)mainThread; // 获得主线程
-(BOOL)isMainThread; // 是否为主线程

安全隐患解决 - 互斥锁
互斥锁使用格式
@synchronized(锁对象) { // 需要锁定的代码  }
注意:锁定1份代码只用1把锁,用多把锁是无效的

互斥锁的优缺点
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源

互斥锁的使用前提:多条线程抢夺同一块资源

相关专业术语:线程同步
线程同步的意思是:多条线程按顺序地执行任务
互斥锁,就是使用了线程同步技术

原子属性(线程安全)
  • 原子属性(线程安全),是针对多线程设计的,是默认属性
  • 多个线程在写入原子属性时(调用 setter 方法),能够保证同一时间只有一个线程执行写入操作
  • 原子属性是一种单(线程)写多(线程)读的多线程技术
  • 原子属性的效率比互斥锁高,不过可能会出现脏数据
  • 在定义属性时,必须显示地指定 nonatomic
原子性(atomic):在多个线程的环境下,只有一个线程,能对属性进行赋值,读取没有线程的限制(自旋锁)。
非原子性:读写都没有限制。

自旋锁和互斥锁区别:自旋锁的执行效率比互斥锁高
共同点:都能够保证同一时间,只有一条线程执行锁定范围的代码
不同点互斥锁:如果发现有其他线程正在执行锁定的代码,线程会进入休眠状态,等待其他线程执行完毕,打开锁之后,线程会被唤醒
      自旋锁:如果发现有其他线程正在执行锁定的代码,线程会以死循环的方式,一直等待锁定代码执行完成
结论
自旋锁更适合执行非常短的代码
无论什么锁,都是要付出代价

UI线程不安全:为了保证性能,不加锁。

当重写了getter & setter 方法后,系统就不会自动生成对应的变量
手动生成属性对应的成员变量:@synthersize obj = _obj;

weak 和 assign 区别:都是弱引用,对象被释放掉后,weak指向0地址, assign为野指针。

线程安全

  • 多个线程进行读写操作时,仍然能够得到正确结果,被称为线程安全
  • 要实现线程安全,必须要用到
  • 为了得到更佳的用户体验,UIKit 不是线程安全的


线程间通讯
  • 在后台线程下载图像
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
1 0
原创粉丝点击