《Linux C编程实战》笔记:创建线程

news2024/11/14 21:33:47

上一章是进程,这一章是线程

有关线程进程的概念之类的请自行学操作系统吧,书里都是偏实战应用的

线程创建函数pthread_create

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
  • pthread_t *thread: 用于存储新线程的标识符的指针。
  • const pthread_attr_t *attr: 指向线程属性的指针,通常为 NULL,表示使用默认属性。
  • void *(*start_routine) (void *): 指向新线程要执行的函数的指针,该函数应该接受一个 void* 参数并返回一个 void*
  • void *arg: 传递给 start_routine 函数的参数。

注意:线程创建成功时,pthread_create函数返回0,若不为0则说明创建线程失败。常见的错误码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如,线程数目过多;后者表示第2个参数代表的线程属性值非法。线程创建成功后,新创建的线程开始运行第3个参数所指向的函数,原来的线程继续运行.

主要是理解第三个参数,这个函数指针是什么意思呢?就是指定线程接下来要执行的程序。创建一个线程,总得要让他干活吧,这个参数就是传递一个函数指针指明线程要干的事。后面有例子可以参考。

那第四个参数就能理解了,函数指针指向的函数可能有参数,所以要在这里传递参数

pthread.h还有一些有用的函数调用

pthread_self 函数用于获取调用线程的线程 ID。

#include <pthread.h>

pthread_t pthread_self(void);

pthread_equal 函数用于比较两个线程的线程 ID 是否相等。

#include <pthread.h>

int pthread_equal(pthread_t thread1, pthread_t thread2);

  • pthread_t thread1: 第一个线程 ID。
  • pthread_t thread2: 第二个线程 ID。

函数返回值是一个整数,如果两个线程的 ID 相等,则返回非零值(真),否则返回零(假)。

pthread_once 函数用于确保一个特定的初始化函数(只执行一次)被多线程环境中的一个线程调用。该函数通常用于在多线程环境中执行某个初始化任务,确保初始化只会执行一次,即便有多个线程同时请求初始化。

以下是 pthread_once 函数的声明:

#include <pthread.h>

int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));

  • pthread_once_t *once_control: 一个指向 pthread_once_t 类型的控制变量的指针,用于确保初始化函数只被执行一次。
  • void (*init_routine)(void): 指向初始化函数的指针

示例程序1

这个示例演示线程创建

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void *thread(void *arg){
    pthread_t newthid;
    newthid=pthread_self();
    printf("this is a new thread,thread ID= %u\n",newthid);
    return nullptr;
}
int main(){
    pthread_t thid;
    printf("main thread,ID is %u\n",pthread_self());
    if(pthread_create(&thid,nullptr,thread,nullptr)!=0){
        printf("thread creation failed\n");
        exit(1);
    }
    sleep(1);
    exit(0);
}

值得说道的就是这个thread函数了,它的返回类型是void *,参数类型也是void *,这是pthread_create函数参数规定的,所以以后写线程执行函数只能这么声明,而且参数只能是一个void *。

在pthread_create函数里,最后一个参数是nullptr,因为我们这个例子的函数不需要使用arg,所以就传了一个空指针。

如果想传递很多值信息,可以用数组或者结构体的方式。

示例程序2

这个示例程序演示pthread_once的使用

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
pthread_once_t once=PTHREAD_ONCE_INIT;
void run(void){
    printf("fuction run is running in thread %u\n",pthread_self());
}
void *thread1(void *arg){
    pthread_t newthid;
    newthid=pthread_self();
    printf("Current thread ID= %u\n",newthid);
    pthread_once(&once,run);
    printf("thread1 ends\n");
    return nullptr;
}
void *thread2(void *arg){
    pthread_t newthid;
    newthid=pthread_self();
    printf("Current thread ID= %u\n",newthid);
    pthread_once(&once,run);
    printf("thread2 ends\n");
    return nullptr;
}
int main(){
    pthread_t thid1,thid2;
    pthread_create(&thid1,nullptr,thread1,nullptr);
    pthread_create(&thid2,nullptr,thread2,nullptr);
    sleep(1);
    printf("main thread exit!\n");
    exit(0);
}

可以看到run函数只在一个线程中运行了一次(这个线程可能是1也可能是2),另一个线程虽然调用了,但是未执行。

其中pthread_once的第二个参数只能是返回类型为void,参数为void的函数,毕竟函数声明就是这样写的。

PTHREAD_ONCE_INIT 是用于初始化 pthread_once_t 变量的宏,它的定义为:

#define PTHREAD_ONCE_INIT 0

这个宏是一个常量,用于初始化 pthread_once_t 类型的变量,表示 pthread_once_t 的初始状态。pthread_once 函数使用这个变量作为参数,确保其中的初始化函数只会被执行一次。

pthread_attr_t结构体

书上说的结构体定义如下

不过我在自己的Linux系统上看了我的pthread_attr_t结构体长这样

union pthread_attr_t
{
  char __size[__SIZEOF_PTHREAD_ATTR_T];
  long int __align;
};
#ifndef __have_pthread_attr_t
typedef union pthread_attr_t pthread_attr_t;
# define __have_pthread_attr_t 1
#endif

可能是Linux的不同?我用的是openeuler,内核好像是centos,这我暂时不是很懂。

不过长得不一样,用法很多还是一样的,这个结构体主要还是设置线程的属性的,一般的设置函数如下:

pthread_attr_init(&attr);//初始化
pthread_attr_setstacksize(&attr,1024);//设置栈大小
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//是否脱离,这里设置的是脱离(detach)

等等,具体都在下面

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

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

相关文章

【AI视野·今日NLP 自然语言处理论文速览 第六十九期】Wed, 3 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 3 Jan 2024 Totally 24 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers An Autoregressive Text-to-Graph Framework for Joint Entity and Relation Extraction Authors Zaratiana Ur…

Presto CLI学习

1. 序言 作为Presto的客户端之一&#xff0c;Presto CLI是一个基于终端的交互式shell&#xff0c;对应presto源码中的presto-cli模块 Presto CLI的本质是一个self-executing jar —— presto-cli-version-executable.jar&#xff0c;就像一个普通的UNIX可执行文件 因此&#…

leaflet呼吸闪烁效果

leaflet呼吸闪烁效果 1.功能背景 这个效果一把用于点击选中&#xff0c;报警提升效果。 2.功能开发 2.1 marker 这个效果还是很好实现&#xff0c;主要通过计时器设置透明度的组合实现。 function setTargetSelect(e){var i 1var int setInterval(() > {if(!e._map…

FineBI实战项目一(4):指标分析之每日订单总额/总笔数

1 明确数据分析目标 统计每天的订单总金额及订单总笔数 2 创建用于保存数据分析结果的表 use finebi_shop_bi;create table app_order_total(id int primary key auto_increment,dt date,total_money double,total_cnt int ); 3 编写SQL语句进行数据分析 selectsubstring(c…

IP地址定位技术筑牢网络安全防线

随着互联网技术的飞速发展&#xff0c;网络安全问题日益凸显&#xff0c;成为人们关注的焦点。如何有效防范和打击网络犯罪&#xff0c;维护国家安全和社会稳定&#xff0c;是摆在我们面前的一项紧迫任务。IP地址定位技术作为网络安全领域的一项重要技术&#xff0c;在防范和打…

【pytorch学习】 深度学习 教程 and 实战

pytorch编程实战博主&#xff1a;https://github.com/lucidrains https://github.com/lucidrains/vit-pytorch

MySQL 8.0.33.0安装、配置教程

一、概述 本文选用的是MySQL 8.0.33.0版本&#x1f449;下载链接 注意&#xff1a; 1.电脑中必须有python&#xff08;没有会导致部分功能无法使用&#xff09; 下载地址&#xff1a; https://www.python.org/ftp/python/3.9.7/python-3.9.7-amd64.exe 2.不同版本之间安装区别…

图像解析力测试

什么是图像解析力测试 图像解析力测试是衡量成像系统性能的关键指标之一,它决定了摄像头捕捉到的图像细节和清晰度。目前主流的图像解析力测试方法主要有TV line检测、MTF检测和SFR检测。 TV line检测主要用于主观测试,通过观察图像中的线条来评估解析力。然而,这种方法缺乏…

Qt/QML编程学习之心得:QProcess进程创建(27)

Qt除了线程Thread,进程也有支持类,那就是QProcess。 可以看出,这个类很大,支持的内容也很多。最简单的使用如: myParam << QString("-param hello") ; bool bRes = QProcess::startDetached("/usr/bin/myApplication", myParam);要启动进程,主…

超维空间M1无人机使用说明书——41、ROS无人机使用yolo进行物体识别

引言&#xff1a;用于M1无人机使用的18.04系统&#xff0c;采用的opencv3.4.5版本&#xff0c;因此M1无人机只提供了基于yolov3和yolov4版本的darknet_ros功能包进行物体识别&#xff0c;识别效果足够满足日常的物体识别使用&#xff0c;如果需要更高版本的yolov7或者yolov8&am…

解决Typescript报错问题[亲测有效]

目录 1、安装 2、报错 3、分析 4、三种更新途径 如果你tsc -v报错&#xff0c;请看这篇文章&#xff0c;本人亲测有效&#xff01; 1、安装 在前端项目中使用TS&#xff0c;需要进行安装&#xff0c;命令为&#xff1a;npm install -g typescript 查看TS版本&#xff1a; …

java基于VUE3+SSM框架的在线宠物商城+vue论文

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…

C练习——鸡兔同笼

题目&#xff1a; 有若干只鸡和兔子在同一个笼子里&#xff0c;从上面数&#xff0c;有98个头&#xff1b;从下面数&#xff0c;有386只脚。问笼中各有几只鸡和兔&#xff1f; 解析&#xff1a; 数学上列二元一次方程组求解&#xff0c;所以采用穷举法&#xff0c;但可以缩小…

【MySQL】字符集与排序规则

在MySQL数据库中&#xff0c;字符集&#xff08;Character Set&#xff09;和排序规则&#xff08;Collation,也称字符集校验规则&#xff09;是重要的概念&#xff0c;它们对于正确存储和比较数据至关重要。 字符集与排序规则 字符集是一组字符的集合&#xff0c;与数字编码…

window使用cpolar实现内网穿透

文章目录 cpolar下载和安装启动和配置cpolar卸载 cpolar下载和安装 进入spolar官网&#xff0c;完成注册&#xff0c;下载相应的cploar版本解压和运行安装文件 配置安装路径&#xff0c;然后选择next&#xff0c;完成即可 启动和配置 点击首页的快捷图标打开网页&#xf…

C++11_可变参数模版

文章目录 前言一、可变参数模版是什么&#xff1f;二、如何使用可变参数模版1.怎么解析可变参数模版2.可变参数模版的实际应用 总结 前言 C11 &#xff0c;添加了许多有用的功能&#xff0c;上章我们主要讲解了右值引用&#xff0c;这章我们来讲解可变参数模版的使用。 提示&a…

Redis:原理速成+项目实战——Redis实战7(优惠券秒杀+细节解决超卖、一人一单问题)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis实战6&#xff08;封装缓存工具&#xff08;高级写法&#xff09;&&缓存总…

实验室管理系统建设方案(LIMS)

1.实验室管理系统 1.1.系统概述 需求描述 实验室管理系统通过先进的数据处理技术对实验室进行全面管理&#xff0c;促进实验室检测流程的信息化、规范化&#xff0c;同时强化实验室检测数据的组织、分析、查询和输出&#xff0c;并对实验过程中的质量因素进行严格控制。 1.1…

分布式锁3: zk实现分布式锁3 使用临时顺序节点+watch监听实现阻塞锁

一 zk实现分布式锁 1.1 使用临时顺序节点 的问题 接上一篇文章&#xff0c;每个请求要想正常的执行完成&#xff0c;最终都是要创建节点&#xff0c;如果能够避免争抢必然可以提高性能。这里借助于zk的临时序列化节点&#xff0c;实现分布式锁 1. 主要修改了构造方法和lock方…

SpringBoot2基础

SpringBoot2 一、初始化项目 ①、创建project ②、构建maven项目 如果选项里没有8的&#xff0c;可以最顶上镜像换成阿里巴巴的&#xff1a;https://start.aliyun.com/ 直接在main函数运行就行 二、SpringBoot入门 1、复制工程 原则 保留工程基础结构抹掉原始工程痕迹 做个…