多线程介绍


进程\线程

  • 进程

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

    1. 1个进程由多个线程组成(1个进程至少要有1个线程)。
    2. 线程是进程的基本执行单元,一个进程的所有任务都在线程中执行。

多线程

  • 多线程

    1. 1个进程中可以开启多个线程,多个线程可以同时执行不同的任务。
    2. 多线程可以提高程序的执行效率。
  • 多线程的原理

    1. 对于单核CPU来说,同一时间,CPU只能处理1个线程,只有1个线程正在执行。
    2. 多线程同时执行的本质:是CPU快速的在多个线程之间的切换。
    3. CPU调度线程的时间足够快,就造成了多线程的“同时”执行。
    4. 如果线程数非常多,CPU会在n个线程之间切换,消耗大量的CPU资源,每个线程被调度的次数会降低,线程的执行效率降低。
  • 多线程的优点

    1. 适当提高程序的执行效率。
    2. 适当提高资源的利用率(CPU、内存)。
    3. 线程上的任务执行完成后,线程会自动销毁
  • 多线程的缺点

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

    1. 一个程序运行后,默认会开启1个线程,称为“主线程”“UI线程”
    2. 主线程一般用来刷新UI界面,处理UI事件
    3. 主线程使用注意:别将耗时的操作放到主线程中,因为耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种卡的坏体验。

同步和异步

  • 同步执行

    1. 写程序的时候都是从上到下,从左到右,代码执行顺序也是从上到下从右到左。
    2. 1个线程执行多个任务,也是依次执行a->b->c。
    3. 1个线程同一时间执行1个任务。
  • 异步执行

    1. 多个线程可以同时执行多个任务。
    2. 多个线程执行多个任务可以同时执行a,b,c。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    // 异步执行
    [self performSelectorInBackground:@selector(test) withObject:nil];
    NSLog(@"over");
}

// 演示耗时操作
- (void)test {
    for (int i = 0; i < 1000 ; i++) {
        // 操作栈空间 速度特别快
        // int n = 10;
        // 操作堆空间,速度慢
        // NSString *str = [NSString stringWithFormat:@"abc %d",i];
        // io操作  input output
        NSLog(@"abc");
    }
}

iOS中多线程的实现方案

  • 技术方案

    1. pthread,C语言的一套通用的多线程API,适用于UNIX\Linux\Windows等系统,跨平台\可移植,使用难度大,线程生命周期需要程序员管理。
    2. NSThread,OC语言,使用更加面向对象,简单易用,可直接操作线程对象,线程生命周期需要程序员管理。
    3. GCD,C语言,旨在替代NSThread等线程技术,充分利用设备的多核,线程生命周期自动管理。
    4. NSOperation,基于OC语言(底层是GCD),比GCD多了一些更简单实用的功能,使用更加面向对象,线程生命周期自动管理。
  • pthread的使用

    1. 使用pthread需要导入头文件#import <pthread.h>
    2. 导入的头文件是跨平台的,都是C语言的。
    3. 通过intpthread_create()函数创建线程。
    4. 在ARC中,使用到和C语言对应的数据类型,应该使用__bridge桥接,在MRC中不需要桥接。在OC中,如果是ARC的话,编译的时候会自动添加retain、release、autorelease,ARC只负责OC的代码,不负责C的代码,如果C语言的框架中,出现create、retain、copy,需要release,而桥接的目的就是解决这个问题。
int pthread_create(pthread_t * __restrict,
    const pthread_attr_t * __restrict,
    void *(*)(void *),
    void * __restrict);
// 参数:
// 第1个参数为指向线程标示符的指针(线程编号的地址)
// 第2个参数用来设置线程属性
// void *(*)(void *) 返回值 (函数指针)(参数)
// void * 返回值类型,类似于OC中的id
// (*) 函数的指针
// (void *) 参数列表
// 第3个参数是线程调用函数指针
// 第4个参数是运行函数的参数

// 返回值:
// 返回0 线程创建成功 此时第1个参数是新线程的编号
// 非0 线程创建失败 返回对应错误码
pthread的使用
  • NSThread
    1. NSThread线程的执行是异步的。
    2. 面向对象的方式创建子线程。
// 通过NSThread开启1个子线程的3种方式
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;
NSThread的使用
  • 线程的状态
    1. 当启动线程后,线程的方法并没有立即执行,而是进入就绪状态,等待CPU的调用。
    2. 线程的状态分为新生状态、就绪状态、运行状态、死亡状态、阻塞状态。
    3. 终止线程前,要释放之前分配的内存。如果是ARC,需要清理C语言框架创建的对象,否则会出现内存泄露。
线程的状态
  • 线程常用属性
    1. 线程名称:设置线程名称可以当线程执行的方法内部出现异常的时候记录异常和当前线程。
    2. 线程优先级:内核调度算法在决定该运行哪个线程时,会把线程的优先级作为考量因素,较高优先级的线程会比较低优先级的线程具有更多的运行机会。较高优先级不保证你的线程具有执行的时间,只是相比较低优先级的线程,它更有可能被调度器选择执行而已。
线程的属性

多线程访问共享资源的问题

  • 互斥锁(线程同步)
    1. 如果多个线程同时读写一个公共变量(属性),可能会出现问题。
    2. 为解决上面的问题,在代码中加入互斥锁(线程同步)
      • 互斥锁保证锁内的代码同一时间,只有一个线程能够执行锁住的代码块。
      • 互斥锁的参数必须是一个对象,任意一个对象都可以,但是不能是线程执行方法中定义的对象,一般用self即可。
      • 互斥锁的原理:每一个对象(NSObject)内部都有一个锁(变量),当有线程要进入@synchronized到代码块中会先检查对象的锁是打开还是关闭状态,默认锁是打开状态(1),如果是线程执行到代码块内部会先上锁(0)。如果锁被关闭,再有线程要执行代码块就先等待,直到锁打开才可以进入。
      • 加锁后程序执行的效率比不加锁的时候要低,因为线程要等待锁,但是锁保证了多个线程同时操作全局变量的安全性。

线程执行到@synchronized
① 检查锁的状态 如果是开锁状态(1)转到② 如果上锁(0)转到⑤
② 上锁(0)
③ 执行代码块
④ 执行完毕 开锁(1)
⑤ 线程等待(就绪状态)

未使用互斥锁 多线程同时访问共享资源引起的问题

使用互斥锁解决多线程访问共享资源的问题
  • 原子属性

    1. 属性中的修饰符:
      • nonatomic:非原子属性。
      • atomic:原子属性(线程安全),针对多线程设计的,属性的修饰符默认值就是atomic。保证同一时间只有一个线程能够写入(但是同一时间多个线程都可以取值)。atomic本身就是一把锁(自旋锁)。单写多读:单个线程写入,多个线程可以读取。
    2. 自旋锁和互斥锁:
      • 相同点:都能保证同一个时间只有一个线程能够执行锁定范围内代码。
      • 不同点:①互斥锁:如果发现其他线程正在执行锁定代码,线程会进入休眠(就绪状态),等其它线程时间片到打开锁后,线程会被唤醒(执行)。
      • 自旋锁:如果发现有其它线程正在锁定代码,线程会用死循环的方式,一直等待锁定的代码执行完成,自旋锁更适合执行不耗时的代码。
      • 无论什么锁,性能都会有损耗(用性能换取数据安全性)。
  • 线程安全

    1. 线程是不安全的,多个线程同时操作同一个全局变量。
    2. 线程安全:在多个线程进行读写操作时,仍然能够保证数据的正确。
    3. UI线程(主线程):
      • 几乎所有UIKit提供的类都不是线程安全的。
      • 所有更新UI的操作都在主线程上执行。
      • Mutable线程是不安全的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 又来到了一个老生常谈的问题,应用层软件开发的程序员要不要了解和深入学习操作系统呢? 今天就这个问题开始,来谈谈操...
    tangsl阅读 4,085评论 0 23
  • 写在前面的话: 这篇博客是我从这里“转载”的,为什么转载两个字加“”呢?因为这绝不是简单的复制粘贴,我花了五六个小...
    SmartSean阅读 4,708评论 12 45
  • Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么? 1...
    AlanGe阅读 1,708评论 0 17
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,682评论 0 11
  • “哈喽!美女。什么时候发糖给我吃啊?”久未联系的中学死党打来电话。 “啊?这个嘛…淡定,淡定啊。总有该你吃的时候呗...
    姗姗读书阅读 308评论 0 0