线程简单总结

线程的概念

线程的定义

线程是进程中的⼀个执行单元,负责当前进程中程序的执行,⼀个进程中至少有⼀个线程 ⼀个进程中是可以有多个线程 多个线程共享同一个进程的资源,每个线程参与操作系统的统一调度

可以简单理解: 进程 = 进程资源 + 主线程 + 子线程+......

线程与进程区别

内存空间 一个进程中多个线程共享同一个内存空间

多个进程拥有独立的内存空间

进程/线程间通讯 线程间通讯方式简单 进程间通讯方式复杂 并发操作,线程比进程更节约资源

联系紧密的任务在并发时优先选择多线程,如果任务之间比较独立,在并发时建议选择多进程。

线程资源

共享进程的资源

同一块地址空间

文件描述符表

每种信号的处理方式(如:SIG_DFL,SIG_IGN或者自定义的信号优先级)

当前工作目录

用户id和组id

独立的资源

线程栈

每个线程都有私有的上下文信息。

线程ID

寄存器的值 errno变量

信号屏蔽字以及调度优先级

线程相关的命令

在 Linux 系统有很多命令可以查看进程,例如 pidstat 、top 、ps ,也可以查看一个进程下的线程

使用 pidstat 命令查看某一个进程下的线程

step 1 : 运行 sem 程序,此程序包含两个进程

step 2 : 查看 sem进程所对应的 id

step 3 : 使用 pidstat 命令查看相应进程的线程

top 命令查看某一个进程下的线程,需要用到 -H 选项在结合 -p 指定 pid

ps 命令结合 -T 选项就可以查看某个进程下所有线程

线程操作

创建线程

创建线程调用 pthread_create 函数

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void * (*start_routine) (void *), void *arg);

函数参数

thread:线程ID变量指针

attr:线程属性,默认属性可设置为NULL

start_routine:线程执行函数

arg:线程执行函数的参数

一旦子线程创建成功,则会被独立调度执行,并且与其他线程并发执行

创建多个线程时,一般由主线程统一创建,并等待释放资源或者分离线程,不要递归创建

1. 多个线程如果任务相同,则可以使用同一个线程执行函数

2. 多个线程如果任务不同,则可以使用不同的线程执行函数

线程的等待、退出和分离

线程退出使用 pthread_exit 函数

Tips:

1. 当主线程调用pthread_exit函数时,进程不会结束,也不会导致其他子线程退出

2. 任何线程调用exit函数会让进程结束

主线程需要等待子线程退出,并释放子线程资源

线程等待调用 pthread_join函数,会阻塞调用线程

线程分为可结合的与可分离的

可结合 :可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源 (如栈)是不释放的。 线程创建的默认状态为可结合的,可以由其他线程调用 pthread_join函数等待子线程退出并 释放相关资源

可分离 :不能被其他线程回收或者杀死的,该线程的资源在它终止时由系统来释放。

线程分离调用 pthread_detach 函数

注意线程分离函数不会阻塞线程的执行

线程间通信

主线程向子线程传递参数

通过 pthread_create 函数的第4个参数 arg 进行传递

子线程给主线程传递参数

子线程给主线程传参的方式如下:

在子线程将需要返回的值存储在 pthread_exit 函数中的 retval 参数中

在主线程中通过 pthread_join 函数的第2个参数 retval 得到返回, pthread_join 函数会将线程的 返回值(指针)保存到 retval 中

线程互斥锁

关于线程互斥锁

线程的主要优势在于能够通过全局变量来共享信息,不过这种便捷的共享是有代价的:

必须确保多个线程不会同时修改同一变量 某一线程不会读取正由其他线程修改的变量,实际就是 不能让两个线程同时对临界区进行访问 线程互斥锁则可以用于解决多线程资源竞争问题

将数字字符串转换为整数 int atoi(const char *nptr)

 1. 线程互斥锁工作机制: 当线程A获得锁,另外一个线程B在获得锁时则会阻塞,直到线程A释放锁,线程B才会获得锁。

2. 线程互斥锁工作原理 :本质上是一个pthread_mutex_t类型的变量,假设名为 v

当 v = 1,则表示当前临界资源可以竞争访问 ,得到互斥锁的线程则可以访问,此时 v = 0

当 v = 0,则表示临界资源正在被某个线程访问,其他线程则需要等待

3. 线程互斥锁的特点 :互斥锁是一个 pthread_mutex_t类型的变量,就代表一个互斥锁

如果两个线程访问的是同一个 pthread_mutex_t 变量,那么它们访问了同一个互斥锁

对应的变量定义在 pthreadtypes.h 头文件中,是一个共用体中包含一个结构体

线程互斥锁的初始化

线程互斥锁的初始化方式主要分为两种

1. 静态初始化

定义 pthread_mutex_t 类型的变量,然后对其初始化为 PTHREAD_MUTEX_INITIALIZER pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER

2. 动态初始化

动态初始化主要涉及两个函数 pthread_mutex_init 函数 与 pthread_mutex_destroy 函数

线程互斥锁的操作

线程互斥锁的操作主要分为 获取锁(lock) 与 释放锁(unlock)

获取锁的函数:pthread_mutex_lock

释放锁的函数:pthread_mutex_unlock

线程同步

线程同步:是指在互斥的基础上,通过其它机制实现访问者对 资源的有序访问。

条件变量:线程库提供的专门针对线程同步的机制

生产者与消费者模型原理

1. 在这个模型中,包括生产者线程与消费者线程。通过线程来模拟多个线程同步的过程

2. 在这个模型中,需要以下组件

仓库 : 用于存储产品,一般作为共享资源

生产者线程 : 用于生产产品

消费者线程 :用于消费产品

3.原理: 当仓库没有产品时,则消费者线程需要等待,直到有产品时才能消费 当仓库已经装满产品时,则生产者线程需要等待,直到消费者线程消费产品之后

条件变量

条件变量 允许一个线程就某个共享变量的状态变化通知其他线程,并让其他线程等待这一通知

条件变量初始化

条件变量的本质为 pthread_cond_t 类型的变量,其他线程可以阻塞在这个条件变量上,或者唤醒阻塞 在这个条件变量上的线程。

条件变量的初始化分为静态初始化与动态初始化

1. 静态初始化

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

2. 动态初始化 pthread_cond_init 函

函数原型

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);

函数功能

初始化条件变量

pthread_cond_destroy函数

函数原型

int pthread_cond_destroy(pthread_cond_t *cond);

函数功能

销毁条件变量

条件变量原理
原理分析

基于条件变量的阻塞与唤醒,具体的原理如下图

step 1 :消费者线程判断消费条件是否满足(仓库是否有产品),如果有产品则可以消费,然后解锁

step 2 :当条件满足时(仓库产品数量为0),则调用 pthread_cond_wait 函数,这个函数具体做的事 情如下:

在线程睡眠之前,对互斥锁解锁

让线程进入到睡眠状态

等待条件变量收到信号时,该函数重新竞争锁,并获取锁

step 3 :重新判断条件是否满足,如果满足,则继续调用 pthread_cond_wait 函数

step 4 :唤醒后,从 pthread_cond_wait 返回,条件不满足,则正常消费产品

step 5 :释放锁,整个过程结束

函数使用

pthread_cond_wait

函数原型 int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); 函数功能 阻塞线程,等待唤醒

Tips:

条件变量需要与互斥锁结合使用,先获得锁才能进行条件变量的操作

调用函数后会释放锁,并阻塞线程

一旦线程唤醒,需要重新竞争锁,重新获得锁之后,pthread_cond_wait 函数返回

pthread_cond_signal和pthread_cond_broadcast

函数原型

int pthread_cond_signal(pthread_cond_t *cond);

函数功能

唤醒所有阻塞在某个条件变量上的线程

函数原型

int pthread_cond_broadcast(pthread_cond_t *cond);

函数功能

唤醒所有阻塞在某个条件变量上的线程

Tips:

pthread_cond_signal 函数主要适用等待线程都在执行完全相同的任务

pthread_cond_broadcast 函数主要适用等待线程都执行不相同的任务

条件变量并不保存状态信息,只是传递应用程序状态信息的一种通讯机制,发送信号时若无任何线 程在等待该条件变量,则会被忽略

条件变量代表是一个通讯机制,用于传递通知与等待通知,用户可以设定条件来发送或者等待通知

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值