当前位置: 首页 > news >正文

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*)&param);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,函数参数:

  1. tidp 指向的内存单元被设置为新创建线程的线程ID。
  2. attr 参数用于定制各种不同的线程属性,暂可以把它设置为 NULL,以创建默认属性的线程。(工作中也多用NULL)
  3. 新创建的线程从 start_rtn(函数指针)函数的地址开始运行,该函数只有一个无类型指针参数 arg
  4. 如果需要向 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函数创建线程。 示例 示例&#xff1a;创建一个线程&#xff0c;其作用就是打印线程ID和传入参数。 //demo1 #include <…...

pc端如何做自适应呢?

<!-- 默认html的font-size的大小是16px 1rem 16px --> <!-- 想要实现自适应的前提条件是 当浏览器的窗口发生变化的时候&#xff0c; html的font-size将会跟着发生改变 --> <!-- 实现的步骤如下 --> <!-- 1 借助flexble.js文件 --> <!-- 2 将fle…...

c语言经典测试题8

在c语言经典测试题6的第一题&#xff0c;大家是否想过可不可以将递归参数改为s呢&#xff1f;或许有的人已经试过了&#xff0c;但是发现好像不会有结果&#xff0c;其实是因为s为后置&#xff0c;先试用后加1&#xff0c;然而我们这个是在s出了函数之后才会运行加1操作&#x…...

解决GitHub无法访问的问题:手动修改hosts文件与使用SwitchHosts工具

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…...

ETL数据仓库的使用方式

一、ETL的过程 在 ETL 过程中&#xff0c;数据从源系统中抽取&#xff08;Extract&#xff09;&#xff0c;经过各种转换&#xff08;Transform&#xff09;操作&#xff0c;最后加载&#xff08;Load&#xff09;到目标数据仓库中。以下是 ETL 数仓流程的基本步骤&#xff1a…...

POST参数里加号+变成空格的问题处理

今天遇到个这样的问题&#xff0c;从前端传到后端的加密报文&#xff0c;里面包含了号&#xff0c;但在后端日志输出看出&#xff0c;变成空格。这个是由于经过RSA加密后引起的 解决办法&#xff1a; 1.前端转码&#xff1a;使用encodeURIComponent对参数进行转码 2.后端解码…...

【华为面试基础题】检查是否存在满足条件的数字组合

描述 给定一个正整数数组检查数组中是否存在满足规则的数组组合 规则&#xff1a; AB2C 输入描述&#xff1a; 第一行输出数组的元素个数&#xff0c;接下来一行输出所有数组元素&#xff0c;用空格隔开 输出描述&#xff1a; 如果存在满足要求的数 在同一行里依次输出 规则…...

亚信安慧AntDB数据并行加载工具的实现(一)

1.概述 数据加载速度是评判数据库性能的重要指标&#xff0c;能否提高数据加载速度&#xff0c;对文件数据进行并行解析&#xff0c;直接影响数据库运维管理效率。基于此&#xff0c;AntDB分布式数据库提供了两种数据加载方式&#xff1a; 一是类似于PostgreSQL的Copy命令&am…...

面经 | Java创建线程的三种方式

利用JUC包创建线程的三种方式&#xff1a; 通过继承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…...

通过一篇文章让你了解数据结构和算法的重要性

通过一篇文章让你了解数据结构和算法的重要性 前言一、 什么是数据结构&#xff1f;二、什么是算法&#xff1f;三、数据结构和算法的重要性在校园招聘的笔试中&#xff1a;在校园招聘的面试中&#xff1a;在未来的工作中&#xff1a; 四、如何学好数据结构和算法4.1 死磕代码&…...

python代码优化学习

代码优化对比&#xff1a; 优化前&#xff1a; # 登录系统 xxljob_login() start_time time.time() # 循环处理需要补数的数据 for item in authId_lists: preSettleInfoHandler(item) count 1 print("运行了第" str(count) "个") …...

C#,数值计算,求解微分方程的吉尔(Gear)四阶方法与源代码

1 微分方程 微分方程&#xff0c;是指含有未知函数及其导数的关系式。解微分方程就是找出未知函数。 微分方程是伴随着微积分学一起发展起来的。微积分学的奠基人Newton和Leibniz的著作中都处理过与微分方程有关的问题。微分方程的应用十分广泛&#xff0c;可以解决许多与导数…...

2024年新提出的算法|LEA爱情进化算法(Love Evolution Algorithm)

Love Evolution Algorithm: a stimulus–value–role theory-inspired evolutionary algorithm for global optimization 爱情进化算法Love Evolution Algorithm&#xff0c;LEA&#xff0c;于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的时序报告中有如下变量&#xff1a; Mean: 高斯分布中的μ值&#xff08;平均值&#xff09; Sensit: sensitivity&#xff0c;也就是1个Sigma的值&#xff1b; Corner: Sigma边界的最差值 cell的delay Delay mean N * Delay sigma; cell 的Transition Sl…...

[VNCTF2024]-PWN:preinit解析(逆向花指令,绕过strcmp,函数修改,机器码)

查看保护&#xff1a; 查看ida&#xff1a; 这边其实看反汇编没啥大作用&#xff0c;需要自己动调。 但是前面的绕过strcmp还是要看一下的。 解题&#xff1a; 这里是用linux自带的产生随机数的文件urandom来产生一个随机密码&#xff0c;然后让我们输入密码&#xff0c;用st…...

网络通信技术

▶1.分组交换技术 在网络通信中&#xff0c;数据通过网络节点的某种转发方式&#xff0c;实现从一个端系统到另一个端系统之间的数据传输技术称为数据交换技术。数据交换技术有电路交换、报文交换和分组交换&#xff0c;计算机网络采用分组交换技术。 分组就是源主机(如服务器…...

【刷题】位运算

消失的两个数字 消失的两个数字 “单身狗”进阶版思路 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));// 按位异或的…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...