C语言linux线程库pthread的简单使用教程

news2025/1/13 6:04:08

POSIX线程(pthread)库
POSIX线程库是用于C/C++的基于标准的线程API。它允许产生一个新的并发流程。它在多处理器或多核系统上最为有效,在这些系统中,可以将流程安排在另一个处理器上运行,从而通过并行或分布式处理提高速度。线程比“forking”或生成新进程所需的开销更少,因为系统不会为进程初始化新的系统虚拟内存空间和环境。虽然在多处理器系统上最有效,但在单处理器系统上也可以找到增益。
使用线程在图形界面程序尤为有效,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。

pthread库需要头文件
pthread.h
编译链接参数-lpthread

创建线程

数据类型
pthread_t 线程ID
pthread_attr_t 线程属性
创建线程函数

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
参数说明
thread:返回线程ID, (在bits/pthreadtypes.h文件中定义为unsigned long int类型)
attr:线程属性,如果要使用默认属性直接传递 NULL
start_routine:线程函数,它是一个函数指针类型,返回类型为 void *,参数为一个 void * 类型变量,创建好这样类型的一个函数,将函数名传递进去即可。
arg:线程函数参数的指针,如果有多个参数,可以传递一个指向参数结构体的指针
返回值说明
成功情况下返回 0,失败情况下返回错误码

获取线程ID

pthread_t pthread_self(void);
该函数返回调用它的线程的线程ID

通过线程ID比较线程是否相等

int pthread_equal(pthread_t t1, pthread_t t2);
如果两个线程相等,返回非0值,如果不相等,返回0

分离线程

int pthread_detach(pthread_t thread);
将线程 ID 为 thread 的线程分离出去,所谓分离出去就是指主线程不需要再通过 pthread_join 等方式等待该线程的结束并回收其线程控制块(TCB)的资源,被分离的线程结束后由操作系统负责其资源的回收。
成功情况下返回 0,失败情况下返回错误码。
额外说明
一般来说,主线程是要负责创建出来的子线程的资源回收工作的。如果主线程先于子线程退出并且子线程没有设置为分离状态,那么子线程结束后其资源是无法得到回收的,会造成资源浪费和系统臃肿;如果主线程先于子线程退出但是子线程时分离状态,那么子线程退出的时候操作系统会自动回收其资源。

终止线程

终止线程的三种方式
a. 线程从启动例程返回,返回值就是线程的退出码
b. 线程可以被同一进程中的其他线程取消
取消线程

int pthread_cancel(pthread_t thread);
向线程发送取消请求,成功返回0,失败返回错误码

c. 线程自身调用pthread_ exit()函数
终止线程

void pthread_exit(void *retval);
参数
retval 返回值
pthread_exit()不返回任何值,如果线程未分离,则可以使用pthread_join()从另一个线程检查线程id和返回值。
注意:指针*retval指向的内容不能为函数中局部变量,因为一旦线程函数终止,它们将不再存在。
注意:如果在主线程中调用了 pthread_exit(NULL),则主线程退出,如果子线程存在会继续执行

等待线程结束

int pthread_join(pthread_t th, void **thread_return);
参数:
th 阻塞当前线程,直到th指定的线程终止。线程终止可以通过调用pthread_exit()函数或者被取消
thread_return 如果线程返回不为NULL,返回值将被储存在thread_return

可以在主线程中使用pthread_join()等待子线程执行结束后再退出,否则主线程退出后,未执行完的子线程也会随之结束。

测试线程的使用

#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
void* func_a(void *pointer){
	int i = 0;
	for(i = 0; i < 3; i++){
		sleep(1);
		printf("thread %d running\n",*(int*)&pointer);

	}
}
int main(int argc, char* argv[]){
	pthread_t threadID[5];
	int i = 0;
	//创建线程
	for(i = 0; i < 5; i++){
		pthread_create(&threadID[i],NULL,func_a,(void *)i);
	}
	//等待所有线程结束后再退出主线程
	for(i = 0; i < 5; i++){
		pthread_join(threadID[i],(void**)0);
	}
	return 0;
}

在这里插入图片描述

线程同步

pthread线程库提供三种同步机制:
互斥锁:阻止其他线程访问变量。这强制线程对变量或变量集进行独占访问。
pthread_join() 使线程等待其他线程结束。
条件变量-数据类型 pthread_cond_t

使用线程锁进行数据同步的办法:
线程锁函数

pthread_mutex_t lock; /* 互斥锁定义 */
pthread_mutex_init(&lock, NULL); /* 动态初始化,	成功返回0,失败返回非0 */
pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER; /* 静态初始化 */
pthread_mutex_lock(&lock); /* 阻塞的锁定互斥锁 */
pthread_mutex_trylock(&thread_mutex)/* 非阻塞的锁定互斥锁,成功获得互斥锁返回0,如果未能获得互斥锁,立即返回一个错误码 */
pthread_mutex_unlock(&lock)/* 解锁互斥锁 */
pthread_mutex_destroy(&lock) /* 销毁互斥锁 */

测试线程锁的代码

#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
//定义互斥锁
pthread_mutex_t g_mutex;
int g_ia = 0;
void *func_c(void *pointer){
	while(1){
		//加锁
		//pthread_mutex_lock(&g_mutex);
		g_ia++;
		//解锁
		//pthread_mutex_unlock(&g_mutex);
		sleep(1);
		
	}
	pthread_exit((void**)0);	
}
int main(int argc, char* argv[]){
	pthread_t threadID;
	pthread_create(&threadID,NULL,func_c,NULL);
	//初始化锁
	pthread_mutex_init(&g_mutex,NULL);
	int i = 0;
	for(i = 0; i<5; i++){
		//加锁
		//pthread_mutex_lock(&g_mutex);
		fprintf(stderr,"%d ",g_ia);
		sleep(1);
		fprintf(stderr,"%d ",g_ia);
		sleep(1);
		fprintf(stderr,"%d \n",g_ia);
		//解锁
		//pthread_mutex_unlock(&g_mutex);
		sleep(1);

	}	
	pthread_cancel(threadID);	
	return 0;
}

不加锁,在一个循环内读取频繁的被线程修改
在这里插入图片描述
将加锁的语句注释取消,对数据加锁保护,在每个while循环内数据没有被线程修改
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/179020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flask框架全解

文章目录简介wsgiref安装配置文件方式一&#xff08;debug方式配置&#xff09;方式二&#xff08;环境变量方式&#xff0c;很少见&#xff09;方式三&#xff08;配置文件方式&#xff09;其他配置方式flask app路由组成写法动态路由的过滤查询字符串传参json和form等数据反向…

deepin系统如何安装惠普打印机

deepin系统如何安装惠普打印机 导读 想必现在有很多小伙伴对于deepin系统如何安装惠普打印机 安装惠普打印机的方法方面的知识都比较想要了解&#xff0c;那么今天小好小编就为大家… 想必现在有很多小伙伴对于deepin系统如何安装惠普p1007打印机 安装惠普打印机的方法方面的知…

【图卷积神经网络】02-谱域图卷积介绍

注&#xff1a;本文为第2章谱域图卷积介绍视频笔记&#xff0c;仅供个人学习使用 目录1、图卷积简介1.1 图卷积网络的迅猛发展1.2 回顾&#xff0c;经典卷积神经网络已在多个领域取得成功1.3 两大类数据1.4 经典卷积神经网络的局限&#xff1a;无法处理图数据结构1.5 将卷积扩展…

Python学习基础之快速入门

目录 首先我们下载最新的python版本&#xff1a;3.0 编写一个hello world 什么是python里面的IPO python运行有几种模式 编写一个温度转换器 在windows上执行python程序 官网&#xff1a;Welcome to Python.org Python 是一门易于学习、功能强大的编程语言。它提供了高效的…

保护视力台灯是白光还是暖光?盘点专业护眼的暖光护眼台灯

保护视力的灯光颜色是最接近太阳光最好&#xff0c;而白光与暖光主要是色温来控制的&#xff0c;低色温&#xff08;3000K以下&#xff09;&#xff0c;中性色温&#xff08;4000K左右&#xff09;&#xff0c;高色温&#xff08;5000K以上&#xff09;&#xff0c;低色温的光源…

在不受支持的 Mac 上安装 macOS Ventura、Monterey、Big Sur (OpenCore Legacy Patcher)

在不受支持的 Mac 上安装 macOS Ventura、Monterey、Big Sur (OpenCore Legacy Patcher) 请访问原文链接&#xff1a;https://sysin.org/blog/install-macos-13-on-unsupported-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.s…

RabbitMQ入门与应用

RabbitMQ入门与应用1.初识MQ1.1.同步和异步通讯1.1.1.同步通讯1.1.2.异步通讯1.2.技术对比&#xff1a;2.快速入门2.1.安装RabbitMQ2.2.RabbitMQ消息模型2.3.导入Demo工程2.4.入门案例2.4.1.publisher实现2.4.2.consumer实现2.5.总结3.SpringAMQP3.1.Basic Queue 简单队列模型3…

python机器学习数据建模与分析——pandas中常用函数总结

本文主要对数据建模与分析中常使用到的pandas内置函数进行总结分析&#xff0c;以此来熟悉数据建模与分析的流程。 文章目录一、Pandas数据结构1.1 数据结构—Series1.1.1 Series的创建方式1.1.2 使用索引和获取数据1.2 数据结构—DataFrame1.2.1 DataFrame的创建方式1.2.2 使用…

变速积分PID算法及仿真

在普通的PID 控制算法中&#xff0c;由于积分系数k是常数&#xff0c;所以在整个控制过程中&#xff0c;积分增量不变。而系统对积分项的要求是&#xff0c;系统偏差大时积分作用应减弱甚至全无&#xff0c;而在偏差小时则应加强。积分系数取大了会产生超调&#xff0c;甚至积分…

强化学习笔记:基于价值的学习之价值迭代(python实现)

目录 1. 前言 2. 数学原理 3. 实现 3.1 Planner类 3.2 ValueIterationPlanner类 4. 运行结果及分析 1. 前言 在强化学习中&#xff0c;根据是否依赖于&#xff08;环境的&#xff09;模型&#xff0c;可以分为有模型&#xff08;model-based&#xff09;…

通信原理简明教程 | 模拟调制传输

文章目录1 模拟幅度调制1.1 模拟幅度调制的基本原理1.2 DSB-SC调制和AM调制1.3 SSB调制和VSB调制2 模拟角度调制2.1 角度调制的基本概念2.2 窄带调频和宽带调频2.3 调频信号的产生方法3 模拟调制系统的解调3.1 相干解调3.2 非相干解调4 模拟调制系统的抗噪声性能4.1 抗噪声性能…

Service Mesh

Service Mesh 参考如下文章&#xff1a;可以将此文章看作为下面文章的结合&#xff1a; https://zhuanlan.zhihu.com/p/61901608 https://philcalcado.com/2017/08/03/pattern_service_mesh.html https://zhuanlan.zhihu.com/p/153105848?from_voters_pagetrue 微服务演化进…

浅谈 开源许可证

目录浅谈 开源许可证一、什么是开源许可证1.1 什么是开源1.2 什么是开源许可证Copyleft 许可证&#xff08;Copyleft 许可证&#xff09;宽松许可证&#xff08;permissive 许可证&#xff09;二、为什么要有开源许可证2.1、No License&#xff1a;没有开源许可证意味着什么2.2…

38.Isaac教程--AprilTags

AprilTags ISAAC教程合集地址文章目录AprilTags源码Isaac Codelet运行示例应用程序在主机系统上运行示例应用程序在 Jetson 上运行应用程序在 Websight 中查看应用程序的输出AprilTags 是一种流行的基准标记形式。 它在机器人技术中有广泛的应用&#xff0c;包括对象跟踪、视觉…

数据挖掘领域十大经典算法

一、什么是数据挖掘&#xff1f;数据挖掘是人工智能和数据库领域研究的热点问题&#xff0c;所谓数据挖掘是指从数据库的大量数据中揭示出隐含的、先前未知的并有潜在价值的信息的非平凡过程。数据挖掘是一种决策支持过程&#xff0c;它主要基于人工智能、机器学习、模式识别、…

蓝桥杯STM32G431RBT6学习——USART

蓝桥杯STM32G431RBT6学习——USART 前言 串口在蓝桥杯近几届中考频也相对较高&#xff08;十三、十二届均考&#xff09;&#xff0c;因此必然也要学习一下。 作为后来之秀的开源项目DAP Link不仅支持SWD调试下载&#xff0c;同时还支持串口调试功能&#xff0c;国信长天开…

软件课设(Ⅲ)——padavan-ng编译以及内核模块修改

我记得今年的很多笔试面试都遇到了linux相关的操作&#xff0c;答题状况都挺……昂。算是补课吧&#xff0c;正好大四的毕业实习、软3还有研0的项目都需要linux的环境进行推进&#xff0c;记录一下&#xff0c;聊作纪念。 实验要求 编译系统&#xff0c;下载并提交&#xff0c;…

大数据技术之Hadoop(Yarn)

第1章 Yarn资源调度器 我们先来思考下面几个问题&#xff1a; 1&#xff09;如何管理集群资源&#xff1f; 2&#xff09;如何给任务合理分配资源&#xff1f; Yarn是一个资源调度平台&#xff0c;负责为运算程序提供服务器运算资源&#xff0c;相当于一个分布式的操作系统平…

图形编辑器:修改图形 x、y、width、height、rotation

大家好&#xff0c;我是前端西瓜哥。图形编辑器的一个需求&#xff0c;就是可以通过属性面板的输入框设置选中元素的属性值。 项目地址&#xff0c;欢迎 star&#xff1a; https://github.com/F-star/suika 线上体验&#xff1a; https://blog.fstars.wang/app/suika/ 最终效果…

Express框架连接MongoDB数据库操作

在上一篇中已经在Node.js中引入使用了mongoose进行MongoDB数据库的基本操作&#xff0c;在本篇当中在Express框架中来连接数据库以及操作数据库&#xff1b; Express 项目环境 这里是通过全局安装Express框架生产的项目环境&#xff0c;也可以通过局部安装的方式&#xff0c;安…