iOS底层原理总结 - pthreads

pthreads简介

引自 维基百科 实现POSIX 线程标准的库常被称作Pthreads,一般用于Unix-like POSIX 系统,如Linux、 Solaris。但是Microsoft Windows上的实现也存在,例如直接使用Windows API实现的第三方库pthreads-w32;而利用Windows的SFU/SUA子系统,则可以使用微软提供的一部分原生POSIX API。

其实,这就是一套在很多操作系统上都通用的多线程API,所以移植性很强,基于C封装的一套线程框架,iOS上也是适用的。

Pthreads创建线程

- (void)onThread {
    // 1\. 创建线程: 定义一个pthread_t类型变量
    pthread_t thread;
    // 2\. 开启线程: 执行任务
    pthread_create(&thread, NULL, run, NULL);
    // 3\. 设置子线程的状态设置为detached,该线程运行结束后会自动释放所有资源
    pthread_detach(thread);
}

void * run(void *param) {
    NSLog(@"%@", [NSThread currentThread]);

    return NULL;
}

打印结果:
{number = 4, name = (null)}

如果出现pthread_create is invalid in C99报错,原因是没有导入#import

pthread_create(&thread, NULL, run, NULL);

  • 第一个参数&thread是线程对象,指向线程标识符的指针
  • 第二个是线程属性,可赋值NULL
  • 第三个run表示指向函数的指针(run对应函数里是需要在新线程中执行的任务)
  • 第四个是运行函数的参数,可赋值NULL

Pthreads其他相关方法

  • pthread_create():创建一个线程
  • pthread_exit():终止当前线程
  • pthread_cancel():中断另外一个线程的运行
  • pthread_join():阻塞当前的线程,直到另外一个线程运行结束
  • pthread_attr_init():初始化线程的属性
  • pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
  • pthread_attr_getdetachstate():获取脱离状态的属性
  • pthread_attr_destroy():删除线程的属性
  • pthread_kill():向线程发送一个信号

Pthreads常用函数与功能

  • pthread_t用于表示Thread ID,具体内容根据实现的不同而不同,有可能是一个Structure,因此不能将其看作为整数。
  • pthread_equal函数用于比较两个pthread_t是否相等。
int pthread_equal(pthread_t tid1, pthread_t tid2)
  • pthread_self函数用于获得本线程的thread id。
pthread _t pthread_self(void);

Pthreads实现互斥锁

锁可以被动态或静态创建,可以用宏PTHREAD_MUTEX_INITIALIZER来静态的初始化锁,采用这种方式比较容易理解,互斥锁是pthread_mutex_t的结构体,而这个宏是一个结构常量,如下可以完成静态的初始化锁:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;也可以用pthread_mutex_init函数动态的创建,函数原型如:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr)

总共有100张火车票,开启两个线程,北京和上海两个窗口同时卖票,卖一张票就减去库存,使用锁,保证北京和上海卖票的库存是一致的。实现如下。

#import "ViewController.h"
#include 

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self onThread];
}

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
NSMutableArray *tickets;

- (void)onThread {
    tickets = [NSMutableArray array];
    //生成100张票
    for (int i = 0; i < 100; i++) {
        [tickets addObject:[NSNumber numberWithInt:i]];
    }

    //线程1 北京卖票窗口
    // 1\. 创建线程1: 定义一个pthread_t类型变量
    pthread_t thread1;
    // 2\. 开启线程1: 执行任务
    pthread_create(&thread1, NULL, run, NULL);
    // 3\. 设置子线程1的状态设置为detached,该线程运行结束后会自动释放所有资源
    pthread_detach(thread1);

    //线程2 上海卖票窗口
    // 1\. 创建线程2: 定义一个pthread_t类型变量
    pthread_t thread2;
    // 2\. 开启线程2: 执行任务
    pthread_create(&thread2, NULL, run, NULL);
    // 3\. 设置子线程2的状态设置为detached,该线程运行结束后会自动释放所有资源
    pthread_detach(thread2);

}

void * run(void *param) {
    while (true) {
        //锁门,执行任务
        pthread_mutex_lock(&mutex);
        if (tickets.count > 0) {
            NSLog(@"剩余票数%ld, 卖票窗口%@", tickets.count, [NSThread currentThread]);
            [tickets removeLastObject];
            [NSThread sleepForTimeInterval:0.2];
        }
        else {
            NSLog(@"票已经卖完了");

            //开门,让其他任务可以执行
            pthread_mutex_unlock(&mutex);

            break;
        }

        //开门,让其他任务可以执行
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

@end

打印结果:


image.png

对锁的操作主要包括:
加锁pthread_mutex_lock()
解锁pthread_mutex_unlock()
和测试加锁pthread_mutex_trylock()三个。
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待。

参考文章:https://juejin.im/post/5ab4a4466fb9a028d14107ff

你可能感兴趣的:(iOS底层原理总结 - pthreads)