《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;…

掌握 Copilot:AI编程的未来

掌握 Copilot&#xff1a;AI编程的未来 前言: 欢迎来到本篇博客&#xff0c;今天我们将深入介绍一款颠覆性的编程辅助工具——Copilot。作为 GitHub Copilot 插件的使用者&#xff0c;你将体验到人工智能在编程领域的前沿应用&#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;…

SpringBoot实用开发(十)-- MongoDB的安装

目录 1. 简单认识 2.使用MongoDB的场景 3.MongoDB的安装 4. MongoDB的服务启动(重点记忆)

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、将故障存储中所…

JS的异步与程序性能相关问题

1、现在与将来 1.1、分块的程序 可以把 JavaScript 程序写在单个 .js 文件中&#xff0c;但是这个程序几乎一定是由多个块构成的。这些块中只有一个是现在执行&#xff0c;其余的则会在将来执行。最常见的块单位是函数 从现在到将来的“等待”&#xff0c;最简单的方法&…