Linux系统上使用C语言创建线程
文章目录
- 一、使用C代码创建线程
- 示例
- API
- 二、线程的相关知识
- 2.1 线程 与 进程 的关系
- 2.2 使用线程的理由
一、使用C代码创建线程
使用pthread_create函数创建线程。
示例
示例:创建一个线程,其作用就是打印线程ID和传入参数。
//demo1
#include <stdio.h>
#include <pthread.h>void* fun1(void *arg)
{printf("t1:%ld thread is create\n", (unsigned long)pthread_self());//pthread_self()打印线程IDprintf("t1: %d\n", *((int*)arg));//函数执行结束,会默认调用 pthread_exit
}int main()
{//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);int ret;int param = 100;pthread_t t1;//1.创建线程// 线程属性 线程函数 线程函数参数ret = pthread_create(&t1, NULL, fun1, (void*)¶m);if(ret == 0){printf("main:create t1 success\n");} else {perror("why t1 fail");}printf("main:%ld\n", (unsigned long)pthread_self());//打印主线程ID//2.等待线程pthread_join(t1, NULL);//等待线程结束,防止进程结束,线程还未执行完毕return 0;
}
API
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号
当pthread_create成功则返回0,函数参数:
- 由
tidp指向的内存单元被设置为新创建线程的线程ID。 attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。(工作中也多用NULL)- 新创建的线程从
start_rtn(函数指针)函数的地址开始运行,该函数只有一个无类型指针参数arg。 - 如果需要向
start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。
pthread_join函数的作用是等待,效果上看是等待线程的执行过程,只有线程执行完毕,才会继续执行下去。可以在fun1函数最后添加while1的死循环来验证:程序不会退出,因为线程一直卡在循环处。感兴趣可以多创建一个t2线程来体验pthread_join函数的作用,一个函数中不带死循环,一个函数中带死循环,都使用pthread_join函数进行等待。
二、线程的相关知识
2.1 线程 与 进程 的关系
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条进程指的是一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并发执行不同的任务。线程包含了表示进程内执行环境必须的信息,其中包括进程中表示线程的 线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno常量以及线程私有数据。进程的所有信息对所有线程都是共享的,包括可执行的程序文本、程序的全局变量和堆内存、栈以及文件描述符。在Unix和类Unix操作系统中线程也被称为轻量级进程(lightweight process),但轻量级进程更多指的是内核线程(kernel thread),而把用户线程(user thread)称为线程。
- 进程——资源分配的最小单位
- 线程——程序执行的最小单位
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但没有独立的地址空间,一个线程死掉就等于整个进程死掉,所以多进程程序比多线程程序健壮,但切换进程时,资源耗费比较大,效率差一些。但对于要求同时进行且又需要共享变量的并发操作,只能使用线程,不能使用进程。
2.2 使用线程的理由
从上面我们知道了进程与线程的区别,其实这些区别也就是我们使用线程的理由。总的来说就是:进程有独立的地址空间,线程没有独立的地址空间(同一进程内的线程共享进程的地址空间)。
使用多线程的理由之一是和进程相比,它是一种非常“节俭”的多任务处理方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。
使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。
多线程程序作为一种多任务、并发的工作方式,有以下的优点:
- 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time
consuming)置于一个新的线程,可以避免这种尴尬的情况。- 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
- 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
相关文章:
Linux系统上使用C语言创建线程
文章目录 一、使用C代码创建线程示例API 二、线程的相关知识2.1 线程 与 进程 的关系2.2 使用线程的理由 一、使用C代码创建线程 使用pthread_create函数创建线程。 示例 示例:创建一个线程,其作用就是打印线程ID和传入参数。 //demo1 #include <…...
pc端如何做自适应呢?
<!-- 默认html的font-size的大小是16px 1rem 16px --> <!-- 想要实现自适应的前提条件是 当浏览器的窗口发生变化的时候, html的font-size将会跟着发生改变 --> <!-- 实现的步骤如下 --> <!-- 1 借助flexble.js文件 --> <!-- 2 将fle…...
c语言经典测试题8
在c语言经典测试题6的第一题,大家是否想过可不可以将递归参数改为s呢?或许有的人已经试过了,但是发现好像不会有结果,其实是因为s为后置,先试用后加1,然而我们这个是在s出了函数之后才会运行加1操作&#x…...
解决GitHub无法访问的问题:手动修改hosts文件与使用SwitchHosts工具
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua,在这里我会分享我的知识和经验。&#x…...
ETL数据仓库的使用方式
一、ETL的过程 在 ETL 过程中,数据从源系统中抽取(Extract),经过各种转换(Transform)操作,最后加载(Load)到目标数据仓库中。以下是 ETL 数仓流程的基本步骤:…...
POST参数里加号+变成空格的问题处理
今天遇到个这样的问题,从前端传到后端的加密报文,里面包含了号,但在后端日志输出看出,变成空格。这个是由于经过RSA加密后引起的 解决办法: 1.前端转码:使用encodeURIComponent对参数进行转码 2.后端解码…...
【华为面试基础题】检查是否存在满足条件的数字组合
描述 给定一个正整数数组检查数组中是否存在满足规则的数组组合 规则: AB2C 输入描述: 第一行输出数组的元素个数,接下来一行输出所有数组元素,用空格隔开 输出描述: 如果存在满足要求的数 在同一行里依次输出 规则…...
亚信安慧AntDB数据并行加载工具的实现(一)
1.概述 数据加载速度是评判数据库性能的重要指标,能否提高数据加载速度,对文件数据进行并行解析,直接影响数据库运维管理效率。基于此,AntDB分布式数据库提供了两种数据加载方式: 一是类似于PostgreSQL的Copy命令&am…...
面经 | Java创建线程的三种方式
利用JUC包创建线程的三种方式: 通过继承Thread类创建线程类实现Runnable接口创建线程类通过Callable和Future接口创建线程 继承Thread类创建线程 class Thread1 extends Thread {Overridepublic void run() {System.out.println("启动线程1");} }实现R…...
【计算机网络】五种IO模型与IO多路转接之select
文章目录 一、五种IO模型二、非阻塞IO1.fcntl2.实现函数SetNoBlock3.轮询方式读取标准输入 三、I/O多路转接之select1.初识select2.select函数原型3.socket就绪条件4.select的特点5.select缺点6.select使用案例--只读取数据的server服务器1.err.hpp2.log.hpp3.sock.hpp4.select…...
通过一篇文章让你了解数据结构和算法的重要性
通过一篇文章让你了解数据结构和算法的重要性 前言一、 什么是数据结构?二、什么是算法?三、数据结构和算法的重要性在校园招聘的笔试中:在校园招聘的面试中:在未来的工作中: 四、如何学好数据结构和算法4.1 死磕代码&…...
python代码优化学习
代码优化对比: 优化前: # 登录系统 xxljob_login() start_time time.time() # 循环处理需要补数的数据 for item in authId_lists: preSettleInfoHandler(item) count 1 print("运行了第" str(count) "个") …...
C#,数值计算,求解微分方程的吉尔(Gear)四阶方法与源代码
1 微分方程 微分方程,是指含有未知函数及其导数的关系式。解微分方程就是找出未知函数。 微分方程是伴随着微积分学一起发展起来的。微积分学的奠基人Newton和Leibniz的著作中都处理过与微分方程有关的问题。微分方程的应用十分广泛,可以解决许多与导数…...
2024年新提出的算法|LEA爱情进化算法(Love Evolution Algorithm)
Love Evolution Algorithm: a stimulus–value–role theory-inspired evolutionary algorithm for global optimization 爱情进化算法Love Evolution Algorithm,LEA,于2024年2月发表在中科院3区SCI期刊 The Journal of Supercomputing。 1、简介 本文提…...
javaWeb个人学习02
会话技术 会话: 用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束.在一次会话中包含多次请求和响应 会话跟踪: 一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一个浏览器,以便在同一次会话的多次请求之间共享数据 会话跟踪方案: …...
EchoServer回显服务器封装与测试
目录 类实现 编译测试 这一篇本质上是为了TcpServer而做的一层封装,让外界调用更加简洁 参考上文 TcpServer服务器管理模块(模块十)-CSDN博客 类实现 echo.hpp #include "../server.hpp"class EchoServer { private:TcpServer _server;private:void OnConnect…...
详解POCV/SOCV的时序报告
POCV/SOCV的时序报告中有如下变量: Mean: 高斯分布中的μ值(平均值) Sensit: sensitivity,也就是1个Sigma的值; Corner: Sigma边界的最差值 cell的delay Delay mean N * Delay sigma; cell 的Transition Sl…...
[VNCTF2024]-PWN:preinit解析(逆向花指令,绕过strcmp,函数修改,机器码)
查看保护: 查看ida: 这边其实看反汇编没啥大作用,需要自己动调。 但是前面的绕过strcmp还是要看一下的。 解题: 这里是用linux自带的产生随机数的文件urandom来产生一个随机密码,然后让我们输入密码,用st…...
网络通信技术
▶1.分组交换技术 在网络通信中,数据通过网络节点的某种转发方式,实现从一个端系统到另一个端系统之间的数据传输技术称为数据交换技术。数据交换技术有电路交换、报文交换和分组交换,计算机网络采用分组交换技术。 分组就是源主机(如服务器…...
【刷题】位运算
消失的两个数字 消失的两个数字 “单身狗”进阶版思路 class Solution { public:vector<int> missingTwo(vector<int>& nums) {int ret 0;int n nums.size();for(int i 0; i < n; i){ret ^ (nums[i] ^ i);}ret ^ (n ^ (n 1) ^ (n 2));// 按位异或的…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
智能体革命:企业如何构建自主决策的AI代理?
OpenAI智能代理构建实用指南详解 随着大型语言模型(LLM)在推理、多模态理解和工具调用能力上的进步,智能代理(Agents)成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同,智能代理能够自主执行工…...
