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

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

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

线程创建函数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.mzph.cn/news/599781.shtml

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

相关文章

设计循环队列——oj题622

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;LeetCode刷题|数据结构|Linux 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 题目要求&#xff1a;应该支持如下操作&#xff1a;示例&#xff1a;提示&#xff1a; 结构体定义队列的创建基本操作判断队列是否为空&#xf…

软件设计模式 --- 类,对象和工厂模式的引入

Q1&#xff1a;什么是软件设计模式&#xff1f; A&#xff1a;软件设计模式&#xff0c;又称设计模式。它是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。综上&…

vmware安装redhat 7.6 操作系统

vmware安装redhat 7.6 操作系统 1、下载redhat 7.6 操作系统镜像文件2、安装redhat 7.6操作系统3、配置redhat 7.6 操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载redhat 7.6 操作系统镜像文件 链接: 盘盘 zwzg 文件名&#xff1a;rhel-serv…

Ubuntu20 编译 Android 12源码

1.安装基础库 推荐使用 Ubuntu 20.04 及以上版本编译&#xff0c;会少不少麻烦&#xff0c;以下是我的虚拟机配置 执行命令安装依赖库 // 第一步执行 update sudo apt-get update//安装相关依赖sudo apt-get install -y libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-de…

无监督学习(K-Means)的认识

目录 一、无监督学习 二、无监督学习和有监督学习的区别 三、K-Means 3.1数据分析 3.2k-meas算法 3.3数据正态化后k-means 3.4找最佳k&#xff08;Elbow Plot&#xff09; 四、k-means算法的优缺点 一、无监督学习 无监督学习是一种机器学习的方法&#xff0c;…

车载 Android之 核心服务 - CarPropertyService 的VehicleHAL

前言: 本文是车载Android之核心服务-CarPropertyService的第二篇&#xff0c;了解一下CarPropertyService的VehicleHAL, 第一篇在车载 Android之 核心服务 - CarPropertyService 解析-CSDN博客&#xff0c;有兴趣的 朋友可以去看下。 本节介绍 AndroidAutomotiveOS中对于 Veh…

【大数据】Zookeeper 集群及其选举机制

Zookeeper 集群及其选举机制 1.安装 Zookeeper 集群2.如何选取 Leader 1.安装 Zookeeper 集群 我们之前说了&#xff0c;Zookeeper 集群是由一个领导者&#xff08;Leader&#xff09;和多个追随者&#xff08;Follower&#xff09;组成&#xff0c;但这个领导者是怎么选出来的…

PTA——逆序的三位数

程序每次读入一个正3位数&#xff0c;然后输出按位逆序的数字。注意&#xff1a;当输入的数字含有结尾的0时&#xff0c;输出不应带有前导的0。比如输入700&#xff0c;输出应该是7。 输入格式&#xff1a; 每个测试是一个3位的正整数。 输出格式&#xff1a; 输出按位逆序…

2025年考研数学题型、题量预测和真题(送35页考研数学大纲详解)

2024年考研的分数线在陆续发布中&#xff0c;在此&#xff0c;六分成长祝福所有努力奋斗的学子们都能进入考研的复试&#xff0c;并顺利录取&#xff0c;2024年9月进入自己心目中的高校、院系和专业继续深造。 与此同时&#xff0c;2025年的考研大幕已经徐徐拉开&#xff0c;现…

书生·浦语大模型全链路开源体系(陈恺|上海人工智能实验室 青年科学家)-听课笔记

大模型重要性 大模型确实已成为发展通用人工智能&#xff08;AGI&#xff09;的重要途径。它们通过整合和处理大量数据&#xff0c;学习语言、图像、声音等多种模式的表示&#xff0c;以此来模拟人类的学习和思维方式。通过不断地学习和优化&#xff0c;这些模型能够在各种任…

DBeaver配置达梦数据库连接

随着信创逐渐推广&#xff0c;达梦数据库也成为流行。下面展示如何使用dbeaver配置达梦数据库连接 1 驱动新建 菜单&#xff0c;数据库->驱动管理器 2 驱动信息填写 选择新建之后&#xff0c;弹出一个填写页面 需要填写的几个关键信息&#xff1a; 驱动名称&#xff1a;…

zookeeper应用场景之分布式的ID生成器

1. 分布式ID生成器的使用场景 在分布式系统中&#xff0c;分布式ID生成器的使用场景非常之多&#xff1a; 大量的数据记录&#xff0c;需要分布式ID。大量的系统消息&#xff0c;需要分布式ID。大量的请求日志&#xff0c;如restful的操作记录&#xff0c;需要唯一标识&#x…

新手学习易语言中文编程,易语言从入门到精通教学

一、教程描述 本套教程共有100集&#xff0c;并且有大量的课件资料&#xff0c;可能是截止到目前为止&#xff0c;最为全面系统的易语言教程了&#xff0c;其中有些视频是.exe文件&#xff0c;可以下载到本地播放。本套易语言教程&#xff0c;大小14.59G&#xff0c;共有6个压…

【Java并发】深入浅出 synchronized关键词原理-下

上一篇文章&#xff0c;简要介绍了syn的基本用法和monter对象的结构&#xff0c;本篇主要深入理解&#xff0c;偏向锁、轻量级锁、重量级锁的本质。 对象内存布局 Hotspot虚拟机中&#xff0c;对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据 (Instance Da…

互联网广告行业发展历程

在20年的历程中&#xff0c;广告主与媒体方持续面对着一些问题&#xff0c;一些核心问题推动了行业的迭代。 互联网广告经过了20年左右的高速发展&#xff0c;已愈发成熟&#xff0c;其历程是有趣的。 对互联网广告发展的理解&#xff0c;网上的文章并不多&#xff0c;已有的…

第12课 利用openCV检测物体是否运动了

FFmpeg与openCV绝对是绝配。前面我们已经基本熟悉了FFmpeg的工作流程&#xff0c;这一章我们重点来看看openCV。 在前面&#xff0c;我们已经使用openCV打开过摄像头并在MFC中显示图像&#xff0c;但openCV能做的要远超你的想像&#xff0c;比如可以用它来实现人脸检测、车牌识…

【Netapp数据恢复】Netapp存储lun被删除如何恢复数据?

Netapp存储数据恢复环境&故障情况&#xff1a; 某单位一台Netapp存储&#xff0c;该Netapp存储内共有数十块SAS硬盘。 工作人员误操作删除了Netapp存储中12个lun&#xff0c;删除的数据包括客户信息和其他重要数据。 Netapp存储数据恢复过程&#xff1a; 1、将故障存储中所…

C#利用openvino部署PP-TinyPose人体姿态识别

【官方框架地址】 github.com/PaddlePaddle/PaddleDetection 【算法介绍】 关键点检测算法往往需要部署在轻量化、边缘端设备上&#xff0c;因此长期以来都存在一个难题&#xff1a;精度高、速度则慢、算法体积也随之增加。而PP-TinyPose的出世彻底打破了这个僵局&#xff0c…

43 tmpfs/devtmpfs 文件系统

前言 在 linux 中常见的文件系统 有很多, 如下 基于磁盘的文件系统, ext2, ext3, ext4, xfs, btrfs, jfs, ntfs 内存文件系统, procfs, sysfs, tmpfs, squashfs, debugfs 闪存文件系统, ubifs, jffs2, yaffs 文件系统这一套体系在 linux 有一层 vfs 抽象, 用户程序不用…

Selenium库和ChromeDriver谷歌驱动最新版安装

1.安装selenium库 使用pip安装第三方库selenium&#xff0c;速度较慢。 pip install selenium 使用国内清华源安装第三方库selenium&#xff0c;速度较快。 pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple 2.安装谷歌浏览器驱动 驱动下载链接&#x…