初识 Linux线程

再学习完Linux进程后,本期,我们来讲解Linux线程

1.为什么需要线程

在之前学习进程前,我们写的所有代码几乎都是单个执行流的,也就是说我们的代码只有一条路走.

在学习进程后,我们可以通过fork进行进程创建,给进程分配任务进行多执行流执行任务,问题来了

那我们为什么还需要线程呢

1.线程是什么,线程的特性(在Linux下)

1.相对于进程与进程之间,一个进程下的线程与线程之间都是共享该进程的大部分地址空 间,也就共 享了大部分进程数据

2.一切进程至少 都有一个执行线程

3.线程在进程内部运行 ,本质是在进程地址空间内运行

4.在Linux系统中,在CPU眼中,看到的都是进程 ,PCB都要比传统的进程更加轻量化

5.透过进程虚拟地址空间,线程之间可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流

1.对比windows

在Linux下,单叫线程可能并不准确,我们更愿意称之为轻量级进程,相对于Windows而言,Linux的线程就优雅许多

**Windows:**对于线程的管理是单独额外管理,明确的区分线程和进程,对线程也就单独组织,进程中再用指针指向组织线程的地址.

Linux:线程之间共享进程地址空间,在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是"一个进程内部的控制序列",也就是轻量级进程,而轻量级进程之间会共享进程地址空间

所以也就相当于Linux中是没有线程的,只存在轻量级进程,线程只是用户级的说法

2.线程(轻量级进程) 轻量在什么地方

由于在Linux下线程为成为轻量级进程更为恰当,下文我就直接称为轻量级进程了

首先,对于cpu来说,它看到的都是进程,轻量级进程也就是一个**更加轻量化的task_struct,**他们和进程并无巨大差别,轻量级进程会轻量在以下地方

  1. 进程地址空间: 轻量级进程与其所属进程共享相同的地址空间。这意味着它们可以访问相同的内存区域,包括代码段、数据段等。

  2. 内核数据结构: 轻量级进程在内核中通常表示为与父进程相同的数据结构,只是某些字段可能会有所不同,例如栈指针、指令指针等。

  3. 文件描述符: 轻量级进程与其父进程共享相同的文件描述符表。这意味着它们可以访问相同的文件、管道、套接字等。

  4. 进程控制块(PCB): 轻量级进程的 PCB 通常与父进程的 PCB 共享很多信息,例如进程 ID、进程状态等。

需要注意的是,每一个轻量级进程都会有自己的独立栈(用户栈) ,这样轻量级进程之间即使调用函数也不会互相干扰.

3.线程间切换

由于在Linux中线程之间是共享进程地址空间 的,而在cpu中,有一块cache缓存 ,然后cpu中的寄存器 会从cache缓存拿数据,它会缓存进程的上下文代码数据 ,大概一般都会有几十 KB 到几 MB左右(还挺大的),所以再进行线程切换的时候,线程不需要 再重新让cache缓存重新加载新的代码数据,这样就不需要冷加载,线程间切换效率也会大大提升

Linux下线程的相关函数

1.pthread_t

创建一个线程单独的线程tid

2. pthread_create

功能:创建一个线程

参数

thread:返回线程ID

attr:设置线程的属性,attr为NULL表示使用默认属性

start_routine:是个函数地址,线程启动后要执行的函数

arg:传给线程启动函数的参数

返回值:成功返回0;失败返回错误码

3.pthread_join

功能:用于等待一个线程结束

参数:

thread:线程ID

retval:拿到线程退出码(这里是二级指针哦)

4.pthread_exit

功能:用于线程自己退出

参数

retval:retval不要指向一个局部变量。

返回值:无返回值,跟进程一样,线程结束的时候无法返回到它的调用者(自身)

使用示例:

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <pthread.h>
using namespace std;
void *func1(void *args)
{
    string threadname = (char *)args;
    cout << threadname << endl;
    int cnt = 5;
    while (cnt--)
    {
        sleep(1);
        cout <<"I'm thread pid::"<< getpid() << endl;
    }
    // return (void*)123;
    pthread_exit((void *)123); // 线程退出
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, func1, (void *)"pthread1");

    int cnt = 10;
    while (cnt--)
    {
        cout <<"I'm main pid::"<< getpid() << endl;
        sleep(1);
    }
    // 主线程
    void *ret = nullptr; // 拿到线程退出码
    int n = pthread_join(tid, &ret);
    std::cout << "main thread quit, n=" << n << " main thread get a ret: " << (long long)ret << std::endl; // void*8个字节
    return 0;
}
相关推荐
No0d1es20 分钟前
电子学会青少年软件编程(C/C++)5级等级考试真题试卷(2024年6月)
c语言·c++·算法·青少年编程·电子学会·五级
炫友呀1 小时前
Centos 更新/修改宝塔版本
linux·运维·centos
闻道且行之1 小时前
嵌入式|VNC实现开发板远程Debian桌面
运维·debian·嵌入式
DjangoJason2 小时前
C++ 仿RabbitMQ实现消息队列项目
开发语言·c++·rabbitmq
向日葵.2 小时前
fastdds.ignore_local_endpoints 属性
服务器·网络·php
IT成长日记2 小时前
【自动化运维神器Ansible】Playbook中的when条件判断:精细化控制任务执行
运维·自动化·ansible·playbook·when·条件判断
weixin_307779134 小时前
VS Code配置MinGW64编译GNU 科学库 (GSL)
开发语言·c++·vscode·算法
昵称为空C4 小时前
SpringBoot接口限流的常用方案
服务器·spring boot
Peter_Deng.4 小时前
Linux 下基于 TCP 的 C 语言客户端/服务器通信详解(三个示例逐步进阶)
服务器·c语言·网络
花小璇学linux5 小时前
imx6ull-驱动开发篇24——Linux 中断API函数
linux·驱动开发·嵌入式软件