C++学习之线程

目录

1.进程和线程的概念

2.线程内核三级映射

3.线程优缺点

4.创建线程和获取线程ID的函数

5.创建子线程

6.循环创建N个子线程

7.子线程传参地址错误演示分析

8.主、子线程共享全局变量、堆空间

9.线程退出

10.pthread join回收线程退出值

11.pthread_cancel

12.杀死线程pthread_cancel

13.进程线程对比

14.线程属性简介


1.进程和线程的概念

- Linux 系统中,线程 LWP 称之为:轻量级的进程。
- 进程:有独立的进程地址空间, 有独立的 pcb。 —— 最小资源分配单位。
- 线程:有独立的pcb,没有独立的进程地址空间。(与其他线程共享) —— 最小执行单位。

![1584326812185](课堂笔记10.assets/1584326812185.png)

- 一个创建了线程的进程,本身也沦落 为线程。

![1584327010849](课堂笔记10.assets/1584327010849.png)

- LWP 号: cpu 划分时间片依据。  —— 线程 最小执行单位。
    - 查看LWP号命令: ps -Lf 进程pid 

2.线程内核三级映射

3.线程优缺点

- 优点:
    - 并发性强。  
    - 开销小。
    - 数据通信方便。
- 缺点:
    - 库函数,稳定性差。
    - 调试、编写困难
    - 对信号支持差。
- 结论:既能使用进程开发,也能使用线程开发的程序,首选 线程。

4.创建线程和获取线程ID的函数

```c
#include <pthread.h>
pthread_t pthread_self(void);   // 获取线程id, 在进程内部标识线程身份。

返回线程id。 没有错误!
```

5.创建子线程

```c
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
参1: 传出参数,新子线的 线程id
参2: 线程属性。默认传 NULL, 表使用默认属性。
参3: 子线程回调函数。pthread_create 调用成功,该函数会被自动调用起来。
参4: 参3 的参数。
返回值:
    成功:0
    失败:直接返回错误号!

6.循环创建N个子线程

```c
// 子线程主函数
void *tfn(void *arg)
{
    printf("tfn : pid = %d, pthread_id = %lu\n", getpid(), pthread_self());
    return NULL;
}
int main(int argc, char *argv[])
{
    pthread_t tid;

    // 创建子线程
    int ret = pthread_create(&tid, NULL, tfn, NULL);
    if (ret != 0)
        fprintf(stderr, "pthread_create err:%s\n", strerror(ret));

    printf("main : pid = %d, pthread_id = %lu\n", getpid(), pthread_self());
    sleep(1);        // 给子线程执行时间

    return 0;        // 释放

7.子线程传参地址错误演示分析

8.主、子线程共享全局变量、堆空间

// 阻塞 回收线程。
int pthread_join(pthread_t thread, void **retval);
参1:待回收的线程id
参2:传出参数。回收的那个线程的 退出值。
    进程中:main返回值:return 0、 exit(1)  ---> int。 回收进程退出值 wait(int *)
    线程中:线程返回值:pthread_exit --> void *。 回收线程退出值 pthread_join(void **)
返回值:
    成功:0
    失败:直接返回错误号!
```

9.线程退出

```c
// 子线程主题函数
void *tfn(void *arg)
{
    sleep(5);
    //return (void *)74;
    pthread_exit((void *)"hello");
}

int main(int argc, char *argv[])
{
    pthread_t tid;
    //int *retval;    // 用来存储子进程退出值
    char *retval;    // 用来存储子进程退出值

    // 创建子线程
    int ret = pthread_create(&tid, NULL, tfn, NULL);
    if (ret != 0)
        fprintf(stderr, "pthread_create err:%s\n", strerror(ret));

    printf("----------------1\n");
    // 回收子线程退出值
    ret = pthread_join(tid, (void **)&retval);
    if (ret != 0)
        fprintf(stderr, "pthread_join err:%s\n", strerror(ret));

    printf("child thread exit with %s\n", (char *)retval);

    pthread_exit((void *)0);        // 退出主线程
}

10.pthread join回收线程退出值

```c
struct thrd {
    int var;
    char str[256];
};

// 子线程主题函数
void *tfn(void *arg)
{
    struct thrd *tval = (struct thrd *)arg;            //malloc()
    tval->var = 100;
    strcpy(tval->str, "hello thread");

    pthread_exit((void *)tval);
    // return (void *)tval;                // 也可以
}

int main(int argc, char *argv[])
{
    pthread_t tid;
    struct thrd arg, *retval;

    // 创建子线程
    int ret = pthread_create(&tid, NULL, tfn, (void *)&arg);
    if (ret != 0)
        fprintf(stderr, "pthread_create err:%s\n", strerror(ret));

    // 回收子线程退出值
    ret = pthread_join(tid, (void **)&retval);
    if (ret != 0)
        fprintf(stderr, "pthread_join err:%s\n", strerror(ret));
    
    printf("child exit with: var = %d, str= %s\n", retval->var, retval->str);

    // free();
    
    pthread_exit((void *)0);        // 退出主线程
}

```

11.pthread_cancel

- 与进程类似,线程结束时,也有 “僵尸线程” 产生。消耗系统资源。

```c
int pthread_detach(pthread_t thread);  // 设置线程为分离态。
参:待设置为分离的线程id
```

- 设置为 分离态的 线程,在终止时,会自动清理 pcb 内核残留。
- 对于已经分离的线程,使用 pthread_join() 不能正常回收。不能获取线程退出值。

12.杀死线程pthread_cancel

``c
int pthread_cancel(pthread_t thread);
参:待杀死的线程id
```

1. 被 pthread_cancel() 杀死的线程,在使用 pthread_join() 回收,得到的退出值 -1。 
2. pthread_cancel() 杀死线程必须要到达一个 “取消点” (保存点), 才能生效。否则无法杀死线程。
    - 应该在被cancel的线程中,调用 pthread_testcancel() 函数 来 添加 “取消点” (保存点)。

13.进程线程对比

1. return
2. pthread_exit()
3. pthread_cancel()   需要 “保存点”。 —— 进内核,即可得到。

14.线程属性简介

| 线程控制原语     | 进程控制原语   |
| ---------------- | -------------- |
| pthread_create() | fork()         |
| pthread_self()   | getpid()       |
| pthread_exit()   | exit()         |
| pthread_join()   | wait/waitpid() |
| pthread_cancel() | kill()         |
| pthread_detach() |                |
 

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

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

相关文章

element-plus中,表单校验的使用

目录 一.案例1&#xff1a;给下面的表单添加校验 1.目的要求 2.步骤 ①给需要校验的el-form-item项&#xff0c;添加prop属性 ②定义一个表单校验对象&#xff0c;里面存放了每一个prop的检验规则 ③给el-form组件&#xff0c;添加:rules属性 ④给el-form组件&#xff0…

团体设计程序天梯赛L2-025 # 分而治之

文章目录 题目解读输入格式输出格式 思路Ac Code参考 题目解读 在战争中&#xff0c;我们希望首先攻下敌方的部分城市&#xff0c;使其剩余的城市变成孤立无援&#xff0c;然后再分头各个击破。为此参谋部提供了若干打击方案。本题就请你编写程序&#xff0c;判断每个方案的可…

Arduino示例代码讲解:Knock Sensor 敲击感知器

Arduino示例代码讲解:Knock Sensor 敲击感知器 Knock Sensor 敲击感知器功能概述硬件部分:软件部分:代码逐行解释定义常量定义变量`setup()` 函数`loop()` 函数工作原理Knock Sensor 敲击感知器 这段代码是一个Arduino示例程序,用于检测敲击声。它通过读取一个压电元件(p…

【百日精通JAVA | SQL篇 | 第三篇】 MYSQL增删改查

SQL得最核心就是增删改查 一个后端开发&#xff0c;在工作中&#xff0c;最常见的场景就是CRUD。 插入数据 insert into student values (1,zhangsan); 指定列插入数据 同时多个列明之间使用逗号&#xff0c;来分割 insert into student (name) values (zhaoliu); 这个黑框…

ggscitable包通过曲线拟合深度挖掘一个陌生数据库非线性关系

很多新手刚才是总是觉得自己没什么可以写的&#xff0c;自己不知道选什么题材进行分析&#xff0c;使用scitable包ggscitable包后这个完全不用担心&#xff0c;选题多到你只会担心你写不完&#xff0c;写得不够快。 既往咱们使用scitable包交互效应深度挖掘一个陌生数据库&…

ctfshow VIP题目限免 版本控制泄露源码2

根据题目提示是版本控制泄露源码 版本控制&#xff08;Version Control&#xff09;是一种在软件开发和其他领域中广泛使用的技术&#xff0c;用于管理文件或项目的变更历史。 主流的版本控制工具&#xff1a; ‌Git‌&#xff1a;目前最流行的分布式版本控制系统。‌SVN‌&am…

2025-04-05 吴恩达机器学习5——逻辑回归(2):过拟合与正则化

文章目录 1 过拟合1.1 过拟合问题1.2 解决过拟合 2 正则化2.1 正则化代价函数2.2 线性回归的正则化2.3 逻辑回归的正则化 1 过拟合 1.1 过拟合问题 欠拟合&#xff08;Underfitting&#xff09; 模型过于简单&#xff0c;无法捕捉数据中的模式&#xff0c;导致训练误差和测试误…

如何用人工智能大模型,进行作业批改?

今天我们学习人工智能大模型如何进行作业批改。手把手学习视频请访问https://edu.csdn.net/learn/40402/666452 第一步&#xff0c;进入讯飞星火。打开google浏览器&#xff0c;输入百度地址后&#xff0c;搜索”讯飞星火”&#xff0c;在搜索的结果中&#xff0c;点第一个讯飞…

C++学习笔记之 模板|函数模板|类模板

函数模板 类模板 定义&#xff1a;函数模板是建立一个通用函数&#xff0c;它所用到的数据的类型&#xff08;包括返回值类型、形参类型、局部变量类型 &#xff09;可以不具体指定&#xff0c;而是用一个虚拟的类型来代替&#xff08;用标识符占位&#xff09;&#xff0c;在…

正则入门到精通

​ 一、正则表达式入门​ 正则表达式本质上是一串字符序列&#xff0c;用于定义一个文本模式。通过这个模式&#xff0c;我们可以指定要匹配的文本特征。例如&#xff0c;如果你想匹配一个以 “abc” 开头的字符串&#xff0c;正则表达式可以写作 “^abc”&#xff0c;其中 …

对备忘录模式的理解

对备忘录模式的理解 一、场景1、题目【[来源](https://kamacoder.com/problempage.php?pid1095)】1.1 题目描述1.2 输入描述1.3 输出描述1.4 输入示例1.5 输出示例 2、理解需求 二、不采用备忘录设计模式1、代码2、问题3、错误的备忘录模式 三、采用备忘录设计模式1、代码1.1 …

86.方便的double转string属性 C#例子 WPF例子

在C#开发中&#xff0c;属性封装是一种常见的设计模式&#xff0c;它可以帮助我们更好地控制数据的访问和修改&#xff0c;同时提供更灵活的功能扩展。今天&#xff0c;我们就来探讨一个简单而优雅的属性封装示例&#xff1a;Power 和 PowerFormatted。 1. 问题背景 在实际开…

bun 版本管理工具 bum 安装与使用

在使用 node 的过程中&#xff0c;我们可能会因为版本更新或者不同项目的要求而频繁切换 node 版本&#xff0c;或者是希望使用更简单的方式安装不同版本的 node&#xff0c;这个时候我们一般会用到 nvm 或者类似的工具。 在我尝试使用 bun 的时候&#xff0c;安装前第一个想到…

GRE,MGRE

GRE&#xff1a;静态过程&#xff0c;有局限性 R1 &#xff1a; [r1]interface Tunnel 0/0/0 --- 创建一个虚拟的隧道接口 [r1-Tunnel0/0/0]ip address 192.168.3.1 24 --- 给隧道接口分配一个 IP 地址 [r1-Tunnel0/0/0]tunnel-protocol gre --- 定义接口的封装方式 [r1-Tun…

游戏无法启动?XINPUT1_3.dll 丢失的终极解决方案

当你兴奋地启动一款新游戏时&#xff0c;突然弹出一个错误提示——‘程序无法启动&#xff0c;因为计算机中丢失 XINPUT1_3.dll’。这种问题在 PC 玩家中非常常见&#xff0c;尤其是运行一些较老的游戏时。XINPUT1_3.dll 是 DirectX 运行库的关键组件&#xff0c;缺失会导致游戏…

用大语言模型学文学常识

李白的诗句“右军本清真”中的“清真”并非指伊斯兰教信仰&#xff0c;而是对王羲之&#xff08;王右军&#xff09;人格和艺术境界的赞美。以下是对这一问题的详细分析&#xff1a; “清真”的古代含义 在魏晋至唐代的语境中&#xff0c;“清真”一词多用于形容人的品格高洁、…

css炫酷的3D水波纹文字效果实现详解

炫酷的3D水波纹文字效果实现详解 这里写目录标题 炫酷的3D水波纹文字效果实现详解项目概述技术栈核心实现1. 基础布局2. 渐变背景3. 文字效果实现3.1 基础样式3.2 文字漂浮动画 4. 水波纹效果4.1 模糊效果4.2 水波动画 5. 交互效果 技术要点项目难点与解决方案总结 项目概述 在…

八、重学C++—动态多态(运行期)

上一章节&#xff1a; 七、重学C—静态多态&#xff08;编译期&#xff09;-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/146999362?spm1001.2014.3001.5502 本章节代码&#xff1a; cpp/dynamicPolymorphic.cpp CuiQingCheng/cppstudy - 码云 - 开源中…

eventEmitter实现

没有做任何异常处理,简单模拟实现 事件对象的每一个事件都对应一个数组 /*__events {"事件1":[cb1,cb2],"事件2":[cb3,cb4],"事件3":[...],"事件4":[...],};*/class E{__events {};constructor(){}//注册监听回调on(type , callbac…

Mysql 中 B 树 vs B+ 树

&#x1f333; 什么是 B树 和 B树&#xff1f; 它们都是多路平衡查找树&#xff08;M-Way Search Tree&#xff09;&#xff0c;用于提升磁盘读写效率&#xff0c;常用于数据库&#xff08;如 MySQL&#xff09;、操作系统中的索引结构。 &#x1f50d; B树 和 B树 的核心区别…