iOS-底层原理 25:多线程原理

2020-11-02  本文已影响0人  Style_月月

iOS 底层原理 文章汇总

本文的目的在于了解进程、线程、多线程、线程池等的基本概念及原理

线程 和 进程

线程和进程的定义

线程

进程

所以,可以简单的理解为:进程是线程的容器,而线程用来执行任务。在iOS中是单进程开发,一个进程就是一个app进程之间是相互独立的,如支付宝、微信、qq等,这些都是属于不同的进程

进程与线程的关系

进程与线程之间的关系主要涉及两个方面:

两个之间的关系就相当于工厂与流水线的关系,工厂与工厂之间是相互独立的,而工厂中的流水线是共享工厂的资源的,即 进程相当于一个工厂线程相当于工厂中的一条流水线

针对进程和线程,还有以下几点说明:

线程和Runloop的关系

多线程

多线程原理

多线程意义

优点

缺点

多线程生命周期

多线程的生命周期主要分为5部分:新建 - 就绪 - 运行 - 阻塞 - 死亡,如下图所示


多线程声明周期

简要说明,就是处于运行中的线程拥有一段可以执行的时间(称为时间片),

线程的exitcancel说明
- exit:一旦强行终止线程,后续的所有代码都不会执行

- `cancel`:取消当前线程,但是不能取消正在执行的线程

【面试题】线程的优先级越高,是不是意味着任务的执行越快?

并不是,线程执行的快慢,除了要看优先级,还需要查看资源的大小(即任务的复杂度)、以及 CPU 调度情况。在NSThread中,线程优先级threadPriority已经被服务质量qualityOfService取代,以下是相关的枚举值

服务质量枚举

线程池原理

线程池原理

iOS中多线程的实现方案

iOS中的多线程实现方式,主要有四种:pthread、NSThread、GCD、NSOperation,汇总如图所示

多线程实现方案

下面是以上四种方案的简单示例

// *********1: pthread*********
pthread_t threadId = NULL;
//c字符串
char *cString = "HelloCode";
/**
 pthread_create 创建线程
 参数:
 1. pthread_t:要创建线程的结构体指针,通常开发的时候,如果遇到 C 语言的结构体,类型后缀 `_t / Ref` 结尾
 同时不需要 `*`
 2. 线程的属性,nil(空对象 - OC 使用的) / NULL(空地址,0 C 使用的)
 3. 线程要执行的`函数地址`
 void *: 返回类型,表示指向任意对象的指针,和 OC 中的 id 类似
 (*): 函数名
 (void *): 参数类型,void *
 4. 传递给第三个参数(函数)的`参数`
 */
int result = pthread_create(&threadId, NULL, pthreadTest, cString);
if (result == 0) {
    NSLog(@"成功");
} else {
    NSLog(@"失败");
}
    
//*********2、NSThread*********
[NSThread detachNewThreadSelector:@selector(threadTest) toTarget:self withObject:nil];
    
//*********3、GCD*********
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [self threadTest];
});
    
//*********4、NSOperation*********
[[[NSOperationQueue alloc] init] addOperationWithBlock:^{
    [self threadTest];
}];

- (void)threadTest{
    NSLog(@"begin");
    NSInteger count = 1000 * 100;
    for (NSInteger i = 0; i < count; i++) {
        // 栈区
        NSInteger num = i;
        // 常量区
        NSString *name = @"zhang";
        // 堆区
        NSString *myName = [NSString stringWithFormat:@"%@ - %zd", name, num];
        NSLog(@"%@", myName);
    }
    NSLog(@"over");
}

void *pthreadTest(void *para){
    // 接 C 语言的字符串
    //    NSLog(@"===> %@ %s", [NSThread currentThread], para);
    // __bridge 将 C 语言的类型桥接到 OC 的类型
    NSString *name = (__bridge NSString *)(para);
    
    NSLog(@"===>%@ %@", [NSThread currentThread], name);
    
    return NULL;
}

C和OC的桥接

其中涉及C与OC的桥接,有以下几点说明

线程安全问题

当多个线程同时访问一块资源时,容易引发数据错乱和数据安全问题,有以下两种解决方案

互斥锁

针对互斥锁,还需要注意以下几点:

自旋锁

【面试题】:自旋锁 vs 互斥锁

atomic 原子锁 & nonatomic 非原子锁

atomic 和 nonatomic主要用于属性的修饰,以下是相关的一些说明:

【面试题】atomic与nonatomic 的区别

iOS 开发的建议

线程间通讯

Threading Programming Guide文档中,提及,线程间的通讯有以下几种方式

线程间通讯-官方文档说明
上一篇下一篇

猜你喜欢

热点阅读