美文网首页
多线程(一)

多线程(一)

作者: 镜像 | 来源:发表于2021-08-10 14:57 被阅读0次

线程与进程

  • 线程是进程的基本执行单元,一个进程所有任务都在线程中执行

  • 进程想要执行任务,必须得有线程,进程至少要有一条线程

  • 程序启动会默认开启一条线程,这条线程被称为主线程或UI线程

  • 进程实质在系统中正在运行的一个应用程序

  • 每个进程之前是独立的,每个进程均运行在其专用的且受保护的内存空间内

  • 通过“活动监视器”可以查看Mac系统中所开启的进程

进程与线程的关系

地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间
资源拥有:同一进程内的线程共享本进程的资源如内存、I/O、cpu等,但是进程之前的资源是独立的。

  1. 一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
  2. 进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程。
  3. 执行过程:每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须已存在应用程序中,由应用程序提供多个线程执行控制。
  4. 线程是处理器调度的基本单位,但进程不是。
  5. 线程没有地址空间,线程包含在进程地址空间中。

时间片的概念:CPU在多个任务直接进行快速的切换,这个时间间隔就是时间片

  • 单核CPU同一时间,只能处理一个线程
  • 多线程同时执行其实是CPU快速的在多个线程之前切换,CPU调度线程的时间足够快,就造成了多线程的“同时”执行的效果
  • 如果线程数非常多,CPU会在n个线程之间切换,消耗大量的CPU资源,导致每个线程呗调度的次数会降低,线程的执行效率降低
线程生命周期 可调度线程池

饱和策略:

  • AbortPolicy 直接抛出RejectedExecutionExeception异常来阻止系统正常运行
  • CallerRunsPolicy 将任务退回到调度者
  • DisOldestPolicy 丢掉等待最久的任务
  • DisCardPolicy 直接丢弃任务

这四种拒绝策略均实现在RejectedExecutionHandler接口

任务执行速度的影响因素

  1. cpu状态
  2. 任务复杂度
  3. 优先级
  4. 线程状态

优先级反转:

  1. IO 密集型,频繁等待
  2. CPU 密集型,很少等待
    IO比CPU更容易得到优先级提升

优先级影响因素:

  1. 用户指定
  2. 等待的频繁度,频繁调用优先级会降低
  3. 长时间不执行,会提升优先级

互斥锁 发现其他线程执行 当前线程 休眠 (就绪状态) 一直在等打开 唤醒执行
自旋锁 发现其他线程执行 当前线程 询问 - 忙等 耗费性能比较高

在短小精悍的项目里用自旋锁,或者环境资源充足,比如mac环境,用自旋锁

atomic 是原子属性,是为多线程开发准备的,是默认属性!
仅仅在属性的 setter 方法中,增加了锁(自旋锁),能够保证同一时间,只有一条线程对属性进行写操作
同一时间 单(线程)写多(线程)读的线程处理技术
nonatomic 是非原子属性
没有锁!性能高!

在源码中可以看到

if (!atomic) {
    oldValue = *slot;
    *slot = newValue;
} else {
    spinlock_t& slotlock = PropertyLocks[slot];
    slotlock.lock();
    oldValue = *slot;
    *slot = newValue;        
    slotlock.unlock();
}

下面看个面试题:

dispatch_queue_t queue = dispatch_queue_create("sj", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1");
dispatch_async(queue, ^{
    NSLog(@"2");
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    NSLog(@"4");
});
NSLog(@"5");

输出结果顺序是:1 5 2 3 4

image

再看下面一段代码:

dispatch_queue_t queue = dispatch_queue_create("sj", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_async(queue, ^{
    NSLog(@"2");
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    NSLog(@"4");
});
NSLog(@"5");

输出结果是: 1 5 2 崩溃

image

这个会造成死锁。第二个块会往第一个块后面增加一个任务,第二个块任务不执行完,是执行不了第一个块下面的代码,但是第一个块代码不执行完,又不能执行第二个块里面的代码,相互等待造成死锁。

再看一种情况:

dispatch_queue_t queue = dispatch_queue_create("sj", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_async(queue, ^{
    NSLog(@"2");
    dispatch_async(queue, ^{
        NSLog(@"3");
    });
    NSLog(@"4");
});
NSLog(@"5");

输出结果是: 1 5 2 4 3

image

相关文章

  • 多线程介绍

    一、进程与线程 进程介绍 线程介绍 线程的串行 二、多线程 多线程介绍 多线程原理 多线程的优缺点 多线程优点: ...

  • 多线程编程

    多线程编程之Linux环境下的多线程(一)多线程编程之Linux环境下的多线程(二)多线程编程之Linux环境下的...

  • 多线程

    创建一个多线程 创建多线程-继承线程类 创建多线程-实现Runnable接口 创建多线程-匿名类code

  • 带你搞懂Java多线程(五)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二)带你搞懂Java多线程(三)带你搞懂Java多线程(四) ...

  • iOS多线程 NSOperation

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程 pthread、NSThread

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程: GCD

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程运用

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程基础

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS 多线程简介

    一.本文介绍点 1.为什么要学习多线程2.什么是多线程3.多线程的原理4.多线程的优缺点5.多线程的应用6.多线程...

网友评论

      本文标题:多线程(一)

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