Linux 多线程基础

news2024/11/16 17:50:13

文章目录

  • 前言
  • 一、多线程基础函数
      • 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());	// 获取线程id

	pthread_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.coloradmin.cn/o/935221.html

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

相关文章

第二章 Linux基础命令

目录 一、 Linux的目录结构  1.学习目标  2.Linux的目录结构  3.Linux路径的描述方式  4.本小节的总结  5.课后练习 二、 Linux命令入门  2.1 Linux命令基础  1.学习目标  2.什么是命令、命令行  3.Linux命令基础格式  4.本小节的总结 2.2 ls命令入门  1…

KMP算法开荒

文章目录 一 、前言二、 暴力解法三、KMP算法原理3.1 自动子串的指针3.2 跳过多少个字符3.3 next数组 - 暴力3.4 next数组 - 求解 四 KMP实现 一 、前言 字符串匹配 import re print(re.search(www, www.runoob.com).span()) # 在起始位置匹配 print(re.search(com, www.run…

Java“牵手”天猫商品sku信息API接口数据,天猫API接口申请指南

天猫平台商品sku属性信息接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取天猫商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品销量接口API是一种用于获取电商平台上商品sku属性数据的接口&#…

无涯教程-KNN算法 - 寻找最近邻居

K最近邻(KNN)算法是一种监督的ML算法&#xff0c;可用于分类以及回归预测问题&#xff0c;但是&#xff0c;它主要用于行业中的分类预测问题。以下两个属性将很好地定义KNN- 惰性学习算法 - KNN是一种惰性学习算法&#xff0c;因为它没有专门的训练阶段&#xff0c;并且在分…

Java-继承和多态(下)

补全构造方法 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);while (scanner.hasNextInt()) {int x scanner.nextInt();int y scanner.nextInt();int z scanner.nextInt();Sub sub new…

【Python】基于Python的电话簿(Phonebook project)设计【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

使用Rust开发命令行工具

生成二进制文件&#xff0c;将其扔到环境变量的path下即可~ 用rust打造实时天气命令行工具[1] 找到合适的API 使用该api[2] 如请求 api.openweathermap.org/data/2.5/weather?qBeijing&appidyour_key: { "coord": { "lon": 116.3972, "lat&quo…

变天了,国产技术突破让黑黄金变成白菜价,芯片技术变革时代来了

由于众所周知的原因&#xff0c;美国企图利用它掌握的硅基芯片技术体系&#xff0c;阻止中国发展先进芯片&#xff0c;不过中国科技界在一项重要芯片材料方面已取得重大突破&#xff0c;还让这种芯片材料变成白菜价&#xff0c;将改变硅基芯片技术主导的时代。 这种芯片材料就是…

小研究 - JVM 的类装载机制

本文通过对一个类装载实例的分析&#xff0c;阐明了 Java虚拟机的类装载的代理机制和由此定义的命名空间&#xff0c;指出了类装载机制在容器/组件/抽象框架结构中的作用。 目录 1 引言 2 实例 3 分析 3.1 类装载的代理机制 3.2 Java的命名空间 3.3 解决问题 4 应…

全栈之前端 | 1.CSS3必备基础知识学习

关注回复【学习交流群】加入【安全开发运维】答疑交流群 请朋友们【多多点击文中的广告】&#xff0c;支持作者更新更多文章。 目录: 0x00 前言简述 描述: 前面跟随着WeiyiGeeker作者【全栈工程师修炼指南】公众号一起学习了前端基础的知识以及HTML标签、属性、事件、字符集系列…

寻找注册配置中心最佳评测官,赢取丰厚奖品 | 测评开启,开发者请速速集结

评测前请点击文末链接&#xff0c;领取 MSE-Nacos 免费试用&#xff0c;再启动评测。 注册配置中心 MSE-Nacos (以下简称 MSE-Nacos)&#xff0c;即 Nacos 的企业版&#xff0c;开箱即用的 Nacos 云服务&#xff0c;对 Nacos 内核进行企业级稳定性加固&#xff0c;故障自动检测…

统计学补充概念-13-逻辑回归

概念 逻辑回归&#xff08;Logistic Regression&#xff09;实际上是一种用于解决分类问题的统计学习方法&#xff0c;尽管其名称中带有"回归"一词&#xff0c;但它主要用于处理分类任务。逻辑回归用于预测一个事件发生的概率&#xff0c;并将其映射到一个特定的输出…

js的this指向问题

代码一&#xff1a; 这段代码定义了run函数、obj对象&#xff0c;然后我们把run函数作为obj的方法。 function run(){console.log(this);}let obj{a:1,b:2};obj.runrun;obj.run(); 那么我们调用obj的run方法&#xff0c;那么这个方法打印的this指向obj。 分析&#xff1a;即…

第十三课 宾语从句

文章目录 前言一、宾语从句1、主语及物动词宾语从句2、主语双宾动词间接宾语直接宾语3、主语特定及物动词宾语从句&#xff08;作宾语&#xff09;宾补4、主语be某些形容词宾语从句5、动词不定式后面的宾语从句6、动名词后面的宾语从句7、介词后面的宾语从句9、间接引语 前言 一…

基于LOF算法的异常值检测

目录 LOF算法简介Sklearn官网LOF算法应用实例1Sklearn官网LOF算法应用实例2基于LOF算法鸢尾花数据集异常值检测读取数据构造数据可视化&#xff0c;画出可疑异常点LOF算法 LOF算法简介 LOF异常检测算法是一种基于密度的异常检测算法&#xff0c;基于密度的异常检测算法主要思想…

Centos7安装ZK-UI管理界面安装|Maven|Git|

一: JDK1.8安装 参考: Centos7卸载|安装JDK1.8|Xshell7批量控制多个终端 二&#xff1a;Maven安装 2.1&#xff1a;下载maven安装包 maven 下载地址&#xff1a;https://mirror.bit.edu.cn/apache/maven/maven-3/ [rootwww ~]# mkdir -p /usr/local/maven [rootwww ~]# …

【C/C++】多态的概念 | 虚函数 | 虚函数指针

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

Linux操作系统--vi/vim编辑器

1.Vi/Vim简介 Vi 是 Unix 操作系统和类 Unix 操作系统中最通用的文本编辑器。 VIM 编辑器是从 VI 发展出来的一个性能更强大的文本编辑器。可以主动的以字体颜色辨别语法的正确性,方便程序设计。VIM 与 VI 编辑器完全兼容。这里简单的理解为如果你需要使用指令取操作Linux系…

【LeetCode-中等题】142. 环形链表 II

文章目录 题目方法一&#xff1a;哈希表set去重方法二&#xff1a;快慢指针 题目 方法一&#xff1a;哈希表set去重 思路&#xff1a;我们遍历链表中的每个节点&#xff0c;并将它记录下来&#xff1b;一旦遇到了此前遍历过的节点&#xff0c;就可以判定链表中存在环。借助哈希…

nonlocal关键字声明

nonlocal关键字声明 作用 使得内层函数可以使用/修改外层函数的变量 值得注意的是&#xff0c;在未使用nonlocal声明时 对于外层函数中的可变对象&#xff0c;内层函数即可访问&#xff0c;也可以修改 def outer():x, y [1], [2]def inner(z):x.append(1)print(x)print(z)r…