初识 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;
}
相关推荐
Microsoft Word2 分钟前
c++基础语法
开发语言·c++·算法
吃肉不能购16 分钟前
Label-studio-ml-backend 和YOLOV8 YOLO11自动化标注,目标检测,实例分割,图像分类,关键点估计,视频跟踪
运维·yolo·自动化
学Linux的语莫19 分钟前
Ansible使用简介和基础使用
linux·运维·服务器·nginx·云计算·ansible
一只小小汤圆27 分钟前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
qq_3129201129 分钟前
docker 部署 kvm 图形化管理工具 WebVirtMgr
运维·docker·容器
踏雪Vernon29 分钟前
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
linux·docker·容器·harmonyos
Onlooker12930 分钟前
云服务器部署WebSocket项目
服务器
学Linux的语莫43 分钟前
搭建服务器VPN,Linux客户端连接WireGuard,Windows客户端连接WireGuard
linux·运维·服务器
legend_jz1 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
Komorebi.py1 小时前
【Linux】-学习笔记04
linux·笔记·学习