深入理解多线程
一、线程基本概念
1、概述
线程是允许应用程序并发的一种机制。线程共享进程内的所有资源。
线程是调度的基本单位。
每个线程都有自己的 errno。
所有 pthread 函数均以返回 0 表示成功,返回一个正值表示失败。
编译 pthread 程序需要添加链接库(-lpthread)。
线程的主要优势在于,能够通过全局变量来共享信息。同时也引入一个问题,多个线程对临界资源的竞争。
2、线程终止方式
1、线程函数执行 return 语句并返回指定值。
2、线程调用 pthread_exit。
3、调用 pthread_cancel() 取消线程。
4、任意线程调用 exit(), 或者主线程执行 return 语句。
二、Pthreads 数据类型
三、线程接口
1、创建线程
#include <pthread.h>int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
pthread_create() 创建线程通过调用带有 arg 参数的 start_routine 函数开始执行。
2、终止线程
#include <pthread.h>void pthread_exit(void *retval);
3、线程 ID
#include <pthread.h>// 获取当前线程 ID
pthread_t pthread_self(void);// 判断 2 个线程ID是否相等
int pthread_equal(pthread_t t1, pthread_t t2);
4、连接已终止的线程
#include <pthread.h>int pthread_join(pthread_t thread, void **retval);
pthread_join 等待由 thread 标识的线程终止。
如果 pthread_join 传入一个之前已经连接过的线程 ID,将导致无法预知的行为。
默认情况下,线程是可连接的(join),也就是程序退出时,其他线程可以通过调用 pthread_join() 获取其返回状态。
5、线程分离
#include <pthread.h>int pthread_detach(pthread_t thread);
有时,我们不关心程序的返回状态,只是希望系统在线程终止时能够自动清理并移除。在这种情况下,可以调用 pthread_detach 并向 thread 参数传入指定线程的标识符,将该线程标记为处于分离状态。
线程可以通过调用 pthread_detach() 实现自行分离。
一旦线程处于分离状态,就不能再使用 pthread_join() 获取其状态,也无法使其重返可连接状态。
6、线程取消
#include <pthread.h>int pthread_cancel(pthread_t thread);
7、线程可取消性检查
#include <pthread.h>void pthread_testcancel(void);
8、清理函数
#include <pthread.h>void pthread_cleanup_push(void (*routine)(void *),void *arg);
void pthread_cleanup_pop(int execute);
9、向线程发送信号
#include <signal.h>int pthread_kill(pthread_t thread, int sig);
#include <signal.h>
#include <pthread.h>int pthread_sigqueue(pthread_t thread, int sig,const union sigval value);
10、操作线程信号掩码
#include <signal.h>int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
四、线程属性
五、线程同步 - 保护共享变量的访问:互斥量
1、分配互斥量
1、静态分配
pthread_mutex_t mutex;
2、动态分配
#include <pthread.h>int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
2、销毁互斥量
#include <pthread.h>int pthread_mutex_destroy(pthread_mutex_t *mutex);
3、加锁和解锁互斥量
#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
调用 pthread_mutex_lock() 锁定互斥量。如果互斥量当前处于未锁定状态,该调用将锁定互斥量并立即返回。如果互斥量处于锁定状态,pthread_mutex_lock() 调用会一直阻塞,直到该互斥量被解锁。
pthread_mutex_unlock() 解锁调用线程锁定的互斥量,以下行为均为错误:
1、对未锁定的互斥量进行解锁。
2、解锁其他线程锁定的互斥量。
4、互斥量死锁
5、互斥量属性
6、互斥量类型
1、PTHREAD_MUTEX_NORMAL
不具备死锁自检功能。
线程试图对已由自己锁定的互斥量加锁,则发生死锁。
互斥量处于未锁定状态,或由其他线程锁定,对其解锁会导致不确定的结果。
2、PTHREAD_MUTEX_ERRORCHECK
此类互斥量的所有操作都会执行错误检查。
可以作为调试工具,以发现程序在哪里违反了互斥量使用的基本原则。
3、PTHREAD_MUTEX_RECURSIVE
该互斥量维护一个锁计数器。当线程第一次取得互斥量时,会将锁定计数器置1,后续同一线程的每次加锁操作会递增锁定计数器的数值,而解锁操作则会递减计数器计数,只有锁计数器值降至0时,才会释放。
六、线程同步 - 通知状态的改变:条件变量
条件变量允许一个线程就某个共享变量(或其他共享资源)的状态变化通知其他线程。
条件变量总是结合互斥量使用。
所有线程都应该处理虚假的唤醒。
条件变量并不保存状态信息,只是传递应用程序状态信息的一种通讯机制。发送信号时,若无任何线程在等待条件变量,这个信号也就不了了之。
1、分配条件变量
1、静态分配
pthread_cond_t cond;
2、动态分配
#include <pthread.h>int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
2、销毁条件变量
#include <pthread.h>int pthread_cond_destroy(pthread_cond_t *cond);
3、通知条件变量
#include <pthread.h>// 至少唤起一个线程
int pthread_cond_signal(pthread_cond_t *cond);
// 唤起所有阻塞线程
int pthread_cond_broadcast(pthread_cond_t *cond);
4、等待条件变量
#include <pthread.h>int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
七、线程安全
1、可重入性
要诀:避免使用全局变量和静态变量。
2、一次性初始化
#include <pthread.h>int pthread_once(pthread_once_t *once_control,void (*init_routine)(void));
pthread_once_t once_control = PTHREAD_ONCE_INIT;
3、线程特有数据
4、线程局部存储
附录一:多线程示例
1、main.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void* pthread_message_function(void *ptr);int main(int argc, char *argv[])
{pthread_t pthreadID1,pthreadID2;int ret = 0;char *message1 = "thread1";char *message2 = "thread2";/* 1、创建线程1 */ret = pthread_create(&pthreadID1,NULL,pthread_message_function,(void*)message1);if(ret != 0){printf("%s create fail!\r\n",message1);}else{printf("%s create sucess!\r\n",message1);}/* 2、创建线程2 */ret = pthread_create(&pthreadID2,NULL,pthread_message_function,(void*)message2);if(ret != 0){printf("%s create fail!\r\n",message2);}else{printf("%s create sucess!\r\n",message2);}/* 3、休眠一定时间,等待子线程结束 */sleep(10);printf("main thread exit\r\n");return 0;
}void* pthread_message_function(void *ptr)
{int i = 0;/* 分离线程 - 避免僵尸线程产生 */pthread_detach(pthread_self());/* 业务逻辑 */for (i; i<5; i++) {printf("%s thread: %d\n", (char *)ptr, i);sleep(1);}
}
2、makefile
a.out: main.cgcc main.c -o a.out -lpthread.PHONY : clean
clean:rm -rf a.out
3、测试
[root@localhost pthread]# make
gcc main.c -o a.out -lpthread
[root@localhost pthread]# ls
a.out main.c makefile
[root@localhost pthread]# ./a.out
thread1 create sucess!
thread2 create sucess!
thread2 thread: 0
thread1 thread: 0
thread2 thread: 1
thread1 thread: 1
thread2 thread: 2
thread1 thread: 2
thread2 thread: 3
thread1 thread: 3
thread2 thread: 4
thread1 thread: 4
main thread exit
[root@localhost pthread]#
相关文章:

深入理解多线程
一、线程基本概念 1、概述 线程是允许应用程序并发的一种机制。线程共享进程内的所有资源。 线程是调度的基本单位。 每个线程都有自己的 errno。 所有 pthread 函数均以返回 0 表示成功,返回一个正值表示失败。 编译 pthread 程序需要添加链接库(…...
华为OD机试题 - 英文输入法(JavaScript)
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解: 英文输入法题目输入输出示例一输入输出说明示例一输入输出Code…...
64 云原生容器化
文章目录 一、什么是rancher二、为什么使用rancher三、 Rancher与[k8s](https://so.csdn.net/so/search?q=k8s&spm=1001.2101.3001.7020)的关系及区别1、Rancher具有的优势三、rancher安装1、细部介绍四、图形化操作1、执行2、图形化操作1、进行客户机登录rancher2、Ranch…...

IronXL for .NET 2023.2.5 Crack
关于适用于 .NET 的 IronXL 在 C# 中阅读和编辑 Excel 电子表格,无需 MS Office 或 Excel Interop。 IronXL for .NET 允许开发人员在 .NET 应用程序和网站中读取、生成和编辑 Excel(和其他电子表格文件)。您可以读取和编辑 XLS/XLSX/CSV/TS…...

计算机组成原理|第一章(笔记)
目录第一章 计算机系统概论1.1 计算机系统简介1.1.1 计算机的软硬件概念1.1.2 计算机系统的层次结构1.1.3 计算机组成和计算机体系结构1.2 计算机的基本组成1.2.1 冯 诺伊曼计算机的特点1.2.2 计算机的硬件框图1.2.3 计算机的工作过程1.3 计算机硬件的主要技术指标1.3.1 机器字…...

[ vulnhub靶机通关篇 ] Empire Breakout 通关详解
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

IP定位离线库有什么作用?
IP离线是什么意思?我们以丢失手机为例来寻找它,现在手机都有IP定位功能,只要手机开通了IP定位,就能找到手机。iPhone定位显示离线一般是iPhone手机关机了或者iPhone手机中“查找我的iPhone”功能关闭了。如果手机在手中的话可以打…...

[C++]vector模拟实现
目录 前言: 1. vector结构 2. 默认成员函数 2.1 构造函数 无参构造: 有参构造: 有参构造重载: 2.2 赋值运算符重载、拷贝构造(难点) 2.3 析构函数: 3. 扩容 3.1 reserve 3.2 resize…...

DevOps实战50讲-(2)Jenkins配置
1. Docker镜像方式安装拉取Jenkins镜像docker pull jenkins/jenkins编写docker-compose.ymlversion: "3.1" services:jenkins:image: jenkins/jenkinscontainer_name: jenkinsports:- 8080:8080- 50000:50000volumes:- ./data/:/var/jenkins_home/首次启动会因为数据…...

LC-1599. 经营摩天轮的最大利润(贪心)
1599. 经营摩天轮的最大利润 难度中等39 你正在经营一座摩天轮,该摩天轮共有 4 个座舱 ,每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱,但每次轮转都需要支付一定的运行成本 runningCost 。摩天轮每次轮转都恰好转动 1 / 4 周。…...

Umi使用百度地图服务
需求描述 需要在前端页面中使用地图定位功能,所以在前端umi项目中使用百度地图服务,由于umi项目默认没有入口的html文件,所以无法通过常规的在head中加入外链js的方式使用 百度ak zyqeLCzvQPCCNImRu9yRGOqWlEUicxxGreact使用百度api 链接:…...

js中getBoundingClientRect()方法
getBoundingClientRect()返回值是一个 DOMRect 对象,是包含整个元素的最小矩形(包括 padding 和 border-width)。该对象使用 left、top、right、bottom、x、y、width 和 height 这几个以像素为单位的只读属性描述整个矩形的位置和大小。除了 …...
Unity记录2.2-动作-动画、相机、Debug与总结
文章首发及后续更新:https://mwhls.top/4453.html,无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评,非常感谢! 汇总:Unity 记录 摘要:重写了动画触…...

分享十个前端Web3D可视化框架附地址
Three.js:Three.js是一个流行的3D库,提供了大量的3D功能,包括基本几何形状、材质、灯光、动画、特效等。它是一个功能强大、易于使用的框架,广泛用于Web3D可视化应用程序的开发。Three.js:https://threejs.org/Babylon…...

基于WSL2和Clion搭建Win下C开发环境
系列文章目录 一、基于WSL2和Clion搭建Win下C开发环境 二、make、makeFile、CMake、CMakeLists的使用 三、全面、详细、通俗易懂的C语言语法和标准库 文章目录系列文章目录前言WSL2安装WSL常用命令VSCode连接WSLroot密码以systemd启动配置sshClion结语前言 Win下C语言开发环境…...

考研第一天,汤家凤基础班,连续与极限复习笔记
函数连续极限性质保号性证明极值点:夹逼准则二项式展开根号下,大于一,小于一的讨论直接放缩求和分子分母齐次,且分母大一次,用积分单调有界存在极限几个重要的切线放缩证明有界,然后放缩求单调证明有界&…...
聊一聊代码重构——关于变量的代码实践
提炼变量 其目标是将一个复杂表达式或语句分解成更小的部分,并将其存储在变量中。提高代码可读性和复用性 复杂的表达式 有些时候为了方便我们会把业务处理的逻辑写在一起,如果参与处理的内容较多时我们就会创造出一个非常长且难以理解的表达式。当其他…...

Spring之基于注解方式实例化BeanDefinition(1)
最近开始读Spring源码,读着读着发现里面还是有很多很好玩的东西在里面的,里面涉及到了大量的设计模式以及各种PostProcessor注入的过程,很好玩,也很复杂,本文就是记录一下我学习过程中的主干流程。 在开始我们源码解读…...

【STM32】入门(十四):FreeRTOS-任务
1、简述 FreeRTOS应用程序由一组独立的任务构成。 在任何时间点,应用程序中只能执行一个任务,FreeRTOS调度器负责决定所要执行的任务。 每个任务在自己的上下文中执行,不依赖于系统内的其他任务或 FreeRTOS的调度器本身。 FreeRTOS调度器负责…...
apscheduler 的基本介绍和使用
APScheduler有四大组件: 1、触发器 triggers : 触发器包含调度逻辑。每个作业都有自己的触发器,用于确定下一个任务何时运行。除了初始配置之外,触发器是完全无状态的。 有三种内建的trigger: (1)date: 特定…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...