Linux 多线程基础

文章目录

  • 前言
  • 一、多线程基础函数
      • 1. pthread_create
      • 2. pthread_self
      • 3. pthread_exit
      • 4. pthread_join
      • 5. pthread_cancel
      • 6. pthread_detach
  • 二、线程间的共享数据
  • 三、多线程 ,进程对比
  • 总结

前言


一、多线程基础函数

1. pthread_create

创建新的线程。

	#include <pthread.h>int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

参数说明:

  • thread: 用于存储新线程的ID。
  • attr: 线程属性,通常使用NULL表示默认属性。
  • start_routine: 线程的入口函数,线程将从该函数开始执行。
  • arg: 传递给线程入口函数的参数。

pthread_t 的具体实现可能因不同的操作系统而有所变化,但在 Linux 中,它通常是一个整数类型(例如 unsigned long int 或 unsigned int

2. pthread_self

函数返回当前线程的线程标识符(pthread_t 类型)。

	pthread_t pthread_self(void);

线程标识符 tid ,用于在其他线程或线程管理函数中标识当前线程。


3. pthread_exit

用于终止当前单一线程的执行并返回一个指定的退出状态。

	void pthread_exit(void *retval);

函数参数:

  • retval:指向线程的退出状态的指针。可以是指向任何类型的指针,表示线程退出时传递的信息。

通过 pthread_exit,线程可以返回一个指定的退出状态,以便创建者线程或进程可以通过 pthread_join 等函数获取该状态

注意
在多线程环境中,不使用 exit 函数,取而代之使用 pthread_exit 函数,将单个线程退出。
因为 在 任何线程里 exit 会导致进程退出,这样会使其他线程为工作就结束。主线程退出不能使用 return 或 exit。


4. pthread_join

用于阻塞等待指定的线程终止,并获取该线程的退出状态。
它允许一个线程等待另一个线程的完成,以便协调线程的执行顺序和获取线程的返回结果。

	int pthread_join(pthread_t thread, void **retval);

函数参数:

  • thread:要等待的线程的线程标识符(pthread_t 类型)。
  • retval:一个指针的指针,用于存储被等待线程的退出状态。

函数说明:
(1). pthread_join 函数阻塞当前线程,直到指定的线程终止
(2). 当所等待的线程终止后,调用 pthread_join 的线程将被唤醒并继续执行。
(3). pthread_join 函数返回后,调用线程可以通过 retval 参数获取被等待线程的退出状态
(4). 被等待的线程在终止时必须使用 pthread_exit 函数返回一个退出状态,以便被等待线程能够获取到退出状态。

示例代码

#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>void* my_pthread (void *arg)
{int *val = (int*)arg;printf("*val = %d\n",*val);sleep(2);printf("pid = %d, tid = %ld\n", getpid(),pthread_self());	// 获取线程idpthread_exit((void*)val);   // 结束线程,并返回退出状态
}int main(void)
{pthread_t tid;int ret;int val = 10;int *threaf_status;printf("main : pid = %d\n", getpid());ret = pthread_create(&tid,NULL, my_pthread, (void*)&val);	// 创建线程if(ret != 0){printf("pthread_create err\n");}pthread_join(tid, (void **)&threaf_status);	// 阻塞等待回收线程的状态printf("status : %d\n", *threaf_status);pthread_exit(NULL);
}

5. pthread_cancel

用于向指定线程发送取消请求,请求线程终止执行。

	int pthread_cancel(pthread_t thread);

取消点 (Cancellation Point):

取消点是一个线程能够响应取消请求的特定函数调用点。
标准的 POSIX 函数(例如 sleep、read、write 等)都是取消点,线程在这些函数调用时能够接收取消请求。
线程也可以使用 pthread_testcancel 函数主动检查取消请求,并在适当的地方终止自己的执行。

6. pthread_detach

用于将一个已经创建但还未被其他线程回收的线程标记为可分离状态,以便操作系统在线程终止时自动回收线程资源。

	int pthread_detach(pthread_t thread);

在线程创建之后,但在其他线程调用 pthread_join 之前,可以调用 pthread_detach 来将线程设为分离状态。

可分离状态的线程可以在终止时自动释放系统资源,无需其他线程显式回收资源。这样可以避免对线程进行 pthread_join 调用等待线程结束。

二、线程间的共享数据

线程默认共享数据段,代码段等地址空间,常用的是全局变量。
线程共享 全局变量,静态变量, 文件描述符,动态分配的堆内存,数据结构

对于共享资源的访问需要考虑线程安全性,使用适当的同步机制(如互斥锁、条件变量、读写锁等)来避免数据竞争和不一致性的问题。

#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>int num = 20;void* my_pthread (void *arg)
{num = 322;
printf("2 : num = %d\n", num);pthread_exit(NULL);   // 结束线程
}int main(void)
{pthread_t tid;int ret;printf("1 : num = %d\n", num);ret = pthread_create(&tid,NULL, my_pthread, NULL);	// 创建线程if(ret != 0){printf("pthread_create err\n");}sleep(1);printf("3 : num = %d\n", num);pthread_exit(NULL);
}

在这里插入图片描述

三、多线程 ,进程对比

多线程进程
pthread_create()fork()
pthread_self()getpid()
pthread_exit()exit()
pthread_join()wait() / waitpid()
pthread_cancel()kill()

多线程和进程是并发编程中的两个重要概念,它们有着不同的特点和应用场景。下面是它们之间的比较:

  1. 进程(Process):是操作系统中的一个执行单位,具有独立的内存空间、代码和数据,可以拥有多个线程。
    线程(Thread):是进程中的一个执行流程,共享进程的内存空间和资源,每个线程有自己的栈空间,但代码和数据是共享的。
    资源占用:

  2. 进程:每个进程都有独立的地址空间和系统资源,包括内存、文件描述符、CPU等。创建和销毁进程的开销较大。
    线程:线程共享进程的地址空间和系统资源,包括内存、文件描述符等。创建和销毁线程的开销相对较小。
    切换开销:

  3. 进程:进程切换的开销较大,需要保存和恢复整个进程的上下文。
    线程:线程切换的开销较小,因为线程共享进程的地址空间和资源,只需要保存和恢复线程的上下文。
    通信方式:

  4. 进程:不同进程之间的通信需要使用进程间通信(IPC)机制,如管道、消息队列、共享内存等。
    线程:线程之间可以通过共享内存、全局变量等直接进行通信,不需要额外的通信机制。
    可靠性:

  5. 进程:由于进程拥有独立的地址空间,一个进程的崩溃不会影响其他进程。
    线程:由于线程共享进程的地址空间,一个线程的崩溃可能会导致整个进程的崩溃。


总结

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

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

相关文章

使用EventLog Analyzer 进行路由器监控

路由器是任何计算机网络的构建块&#xff0c;引导网络中的流量&#xff0c;管理员需要确保路由器已配置并正常工作&#xff0c;以确保网络安全。 监控路由器中的用户活动 在网络安全方面&#xff0c;与路由器相关的风险是一个严重的问题。具有松散安全策略的网络使入侵者可以…

kafka--技术文档--基本docker中安装<单机>-linux

安装zookeeper 阿丹小科普&#xff1a; Kafka在0.11.0.0版本之后不再依赖Zookeeper&#xff0c;而是使用基于Raft协议的Kafka自身的仲裁机制来替代Zookeeper。具体来说&#xff0c;Kafka 2.8.0版本是第一个不需要Zookeeper就可以运行Kafka的版本&#xff0c;这被称为Kafka Raf…

3 自制一个集群分发脚本

1. 随便取了一个名字&#xff1a;xsync 2. 在一个配置环境变量的目录下&#xff0c;我是放在了/opt/software下&#xff0c;这个路径我是配置了环境变量的。 3. 编辑脚本&#xff1a;vim xsync #!/bin/bash#1. 判断参数个数 if [ $# -lt 1 ] thenecho Not Enough Arguement!…

【⑮MySQL | 视图】概述 | 创建 | 查看 | 更新 | 修改 | 删除

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL视图概述 | 创建 | 查看 | 更新 | 修改 | 删除的分享✨ 目录 前言1.视图概述2.创建视图3.查看视图4.更新视图数据5.修改视图6.删除视图总结 1.视图概述 1.1 为什么使用视图&#xff1f; 视图一方面可以帮我们使…

如何构建多域名HTTPS代理服务器转发

在当今互联网时代&#xff0c;安全可靠的网络访问是至关重要的。本文将介绍如何使用SNI Routing技术来构建多域名HTTPS代理服务器转发&#xff0c;轻松实现多域名的安全访问和数据传输。 SNI代表"Server Name Indication"&#xff0c;是TLS协议的扩展&#xff0c;用于…

2023年国赛 高教社杯数学建模思路 - 案例:随机森林

文章目录 1 什么是随机森林&#xff1f;2 随机深林构造流程3 随机森林的优缺点3.1 优点3.2 缺点 4 随机深林算法实现 建模资料 ## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林&#xff…

数据结构(Java实现)-二叉树(下)

获取二叉树的高度 检测值为value的元素是否存在(前序遍历) 层序遍历 判断一棵树是不是完全二叉树 获取节点的路径 二叉树的最近公共祖先

Docker基本部署和相关操作

1.安装docker服务&#xff0c;配置镜像加速器 1、yum安装并且添加源信息 yum install yum-utils device-mapper-persistent-data lvm2 -y yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo2、修改一些配置信息 sed…

Kaggle回归问题Mercedes——Benz Greener Manufacturing

目录 前言1 题目介绍2 数据清洗3 数据可视化分析4 模型训练5 源码 前言 这是我在大三选修课的课程设计&#xff0c;内容参考了Kaggle上高赞的代码&#xff0c;有详细批注&#xff0c;整体比较基础&#xff0c;结构相对完整&#xff0c;便于初学者学习。这个是一个回归问题&…

⌈算法进阶⌋图论::拓扑排序(Topological Sorting)——快速理解到熟练运用

目录 一、原理 1. 引例&#xff1a;207.课程表 2. 应用场景 3. 代码思路 二、代码模板 三、练习 1、210.课程表Ⅱ&#x1f7e2; 2、2392.给定条件下构造举证&#x1f7e1; 3、310.最小高度树 &#x1f7e1; 一、原理 1. 引例&#xff1a;207.课程表 就如大学课程安排一样&…

21.2 CSS 三大特性与页面布局

1. 开发者工具修改样式 使用开发者工具修改样式, 操作步骤如下: * 1. 打开开发者工具: 在浏览器中右键点击页面, 然后选择检查或者使用快捷键(一般是 F12 或者 CtrlShiftI)来打开开发者工具.* 2. 打开样式编辑器: 在开发者工具中, 找到选项卡或面板, 一般是Elements或者Elemen…

【Go Web 篇】从零开始:构建最简单的 Go 语言 Web 服务器

随着互联网的迅速发展&#xff0c;Web 服务器成为了连接世界的关键组件之一。而在现代编程语言中&#xff0c;Go 语言因其卓越的性能和并发能力而备受青睐。本篇博客将带你从零开始&#xff0c;一步步构建最简单的 Go 语言 Web 服务器&#xff0c;让你对 Go 语言的 Web 开发能力…

线性代数的学习和整理14: 线性方程组求解

目录 1 线性方程组 2 有解&#xff0c;无解 3 解的个数 1 线性方程组 A*xy 3根直线的交点&#xff0c;就是解 无解的情况 无解&#xff1a; 三线平行无解&#xff1a;三线不相交 有解 有唯一解&#xff1a;三线相交于一点有无数解&#xff1a;三条线重叠 2 齐次线性方程组…

Vue的使用

Vue的使用 Vue到底是啥&#xff1f;Vue中包含了两部分虚拟DOM 模块化编程虚拟DOM&#xff0c;在我们重用模板的时候&#xff0c;在Vue中存在虚拟DOM 虚拟DOM是为了更好的去重用我们的DOM (增加元素的时候&#xff0c;先去虚拟DOM找是否存在&#xff0c;如果有那么不用生成&am…

VUE笔记(六)vue路由

一、路由的简介 1、实现生活中的路由 路由&#xff1a;路由其实就是一个key-value对应关系 路由器&#xff1a;用于管理多个路由关系的设备被称为路由器 2、前端的路由 目前使用的前端项目都是单页面的应用&#xff08;SPA&#xff09;&#xff0c;一个项目中只有一个html页…

c语言中编译过程与预处理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、c语言的编译与链接1、编译与链接概述2、编译与链接详解 二、c语言预处理1.c语言中内置的预定义符号2、#define定义标识符3、#define定义宏4、#define 替换规…

CSS scoped 属性的原理

scoped 一、scoped 是什么&#xff1f;二、实现原理 一、scoped 是什么&#xff1f; 在 Vue 组件中&#xff0c;为了使样式私有化&#xff08;模块化&#xff09;&#xff0c;不对全局造成污染&#xff0c;可以在 style 标签上添加 scoped 属性以表示它的只属于当下的模块&am…

数组和指针练习解析(6)

题目&#xff1a; int main() { char *c[] {"ENTER","NEW","POINT","FIRST"}; char**cp[] {c3,c2,c1,c}; char***cpp cp; printf("%s\n", **cpp); printf("%s\n", *--*cpp3)&#xff1b; printf("%s\n&…

数据结构(Java实现)-包装类和泛型

包装类 在Java中&#xff0c;由于基本类型不是继承自Object&#xff0c;为了在泛型代码中可以支持基本类型&#xff0c;Java给每个基本类型都对应了 一个包装类型。 基本数据类型和对应的包装类 装箱和拆箱 装箱操作&#xff0c;新建一个 Integer 类型对象&#xff0c;将 i 的…

【提升接口响应能力的最佳实践】常规操作篇

文章目录 1. 并行处理简要说明CompletableFuture是银弹吗&#xff1f;测试案例测试结论半异步&#xff0c;半同步总结 2. 最小化事务范围简要说明编程式事务模板 3. 缓存简要说明 4. 合理使用线程池简要说明使用场景线程池的创建参数的配置建议 线程池的监控线程池的资源隔离 5…