当前位置: 首页 > news >正文

线程(一) linux

目录

线程概念

资源划分

共享资源与私有资源

私有

共享

优缺点

优点

缺点

linux下的线程

LWP(轻量级进程 Light Weight Progress)

线程控制

线程创建

线程等待

线程退出

获取线程ID

线程分离

简单封装

小知识


线程概念

进程:承担分配系统资源的实体


线程:操作系统调度的基本单位,是进程内部的执行流

不同的线程会被分配去执行不同的函数,作为一个进程内部的多个执行流

资源划分

函数可以看做虚拟地址的集合,不同的线程执行不同的函数相当于拥有不同的虚拟地址资源

共享资源与私有资源

私有

1.线程ID

2.线程的上下文数据

3.栈

4.errno

5.信号屏蔽字

6.调度优先级

共享

1.因为线程在同一地址空间中,所以全局资源(全局函数,全局变量)都是共享的,这里会出现可重入函数的问题

2.文件描述符表

3.信号处理方式

4.当前工作目录

5.用户id和组id

优缺点

优点

1.创建线程比创建进程代价小

2.与进程切换相比,线程切换工作少

因为:

(1).线程切换时,无需切换CR3(CR3中存进程的页目录表基地址)

(2).TLB(缓存) 缓存的数据在线程切换时无需变化,进程切换时要更新

(3).线程切换时cache缓存不用更新,进程切换要更新

 

3.占用资源比进程少

4.能充分利用多处理器的可并行数量

5.在等待IO操作结束的时候,程序可以执行其他任务

6.对于计算密集型应用,可以将计算分解到多个线程中来在多处理器上并行

7.IO密集型应用,线程可以同时等待不同的IO操作,将IO操作重叠来提高性能

缺点

1.太多线程导致性能损失

2.健壮性降低,一个线程出问题,整个进程出问题

3.缺乏访问控制

进程是访问控制的基本单位,一个线程调用某些OS函数会对整个进程造成影响

linux下的线程

1.linux中,内核中,线程的实现是用进程模拟的,复用了进程代码和结构

2.线程在进程的虚拟地址空间中运行,不同的线程访问虚拟地址空间中的一部分资源,通过不同线程执行不同的入口函数实现

LWP(轻量级进程 Light Weight Progress)

linux通过轻量级进程来模拟线程,就是在内核级,linux使用轻量级进程作为线程,只提供轻量级进程的系统调用

而为了适应环境(大多数人都使用线程,而不熟悉轻量级进程),通过外部库封装了一个原生线程库pthread

线程控制

注意:1.使用线程控制函数要引入<pthread.h>头文件

2.链接时要链接pthread库,加' -lpthread'选项

线程创建

pthread_create

thread:输出型参数,线程id  一个无符号长整数(unsigned long int) ,实际上是pthread线程库维护的线程结构体对象的起始地址

attr:线程属性,一般传nullptr即可

start routine:该线程执行的函数

arg:传递给该线程的参数,也就是给函数的参数


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


线程中可以创建线程,这个新线程也是由进程创建的


ps -aL  查看进程

线程等待

pthread_join

thread: 线程id,就是pthread库中表明线程控制块的起始地址

retval :输出参数,获取新线程退出信息,不关心传nullptr即可


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


join会阻塞等待线程执行完毕,主线程最后退出,自动解决子线程僵尸问题

线程退出

四种方式

1.exit 直接终止进程


2.线程函数return


3.pthread_exit  将使用此函数的线程退出

retval :输出参数,获取新线程退出信息,不关心传nullptr即可


4.pthread_cancel   会将指定线程退出

thread: 线程id,就是pthread库中表明线程控制块的起始地址

获取线程ID

pthread_self

线程分离

分离线程:如果不关心线程的返回值,那么使用这个告诉系统,线程退出时,自动释放资源,无需join

默认情况下,新创建的线程是joinable的,线程退出后,需要进行pthread_jioin操作,否则无法释放资源,导致资源泄露


1.如果让子线程自己去分离,因为主线程和多个子线程执行先后不确定,所以要让想办法子线程先执行

2.如果让主线程去分离,在适当位置分离即可

简单封装

#pragma once

#include <iostream>

#include <thread>

#include <functional>

#include <string>

#include <unistd.h>

#include <sys/syscall.h>

#define get_lwp_id() syscall(SYS_gettid)

using func_t = std::function<void()>;

const std::string threadname = "name";

class Thread

{

    bool _running;

    pthread_t _tid;

    pid_t _lwpid;

    std::string _name;

    func_t _func;

public:

    Thread(func_t func,const std::string &name = threadname)    

        :_name(name)

        ,_func(func)

        ,_running(false)

        {}

    ~Thread(){}    

    static void *start_routine(void *args)

    {

        Thread *self = static_cast<Thread*>(args);

        self->_running = true;

        self->_lwpid = get_lwp_id();

        self->_func();

        pthread_exit((void*)0);

    }

    void start()

    {

        int tmp = pthread_create(&_tid,nullptr,start_routine,this);

        if(tmp==0) {std::cout<<"pthread_start success"<<std::endl;}

    }

     

    void Join()

    {

        if(!_running) return;

        int tmp = pthread_join(_tid,nullptr);

        if(tmp==0) {std::cout<<"pthread_join success"<<std::endl;}

    }

};

使用举例

#include "thread.hpp"

#include <vector>

#include <iostream>

void test()

{

    for(int i=0;i<5;i++)

    {

        std::cout<<"runing......"<<std::endl;

        sleep(0.5);

    }

}

int main()

{

    std::vector<Thread> threads;

    for(int i=0;i<5;i++)

    {

        std::string name = "thread-";

        name += std::to_string(i+1);

        Thread t(test,name);

        threads.push_back(t);

    }

    for(int i=0;i<5;i++)

    {

        threads[i].start();

    }

    for(int i=0;i<5;i++)

    {

        threads[i].Join();

    }

    return 0;

}

小知识

1.windows中的线程专门定义了线程结构体及其调度算法

2.多个子线程执行先后顺序不定

3.linux线程库叫做用户级线程,因为使用的是用户级别的pthread库

 

4.主线程使用进程的栈(主线程的栈),子线程使用库内维护的开的新栈,子线程的栈是固定大小的,不会向下增长

5.线程管理不是进程为单位的(每个进程管着自己的线程),是全部系统中的lwp都由pthread库来管理

6.__thread 变量    编译器提供的编译修饰符(内置选项)

将变量声明为子线程自己的变量, 只支持内置类型

http://www.lryc.cn/news/588671.html

相关文章:

  • 使用Dify+fastmcp 实现mcp服务,内含详细步骤与源码
  • Mac IDEA启动报错:Error occurred during initialization of VM
  • Twisted study notes[1]
  • [附源码+数据库+毕业论文+开题报告]基于Spring+MyBatis+MySQL+Maven+jsp实现的车辆运输管理系统,推荐!
  • etcd自动压缩清理
  • easy-ui中的相对路径和绝对路径问题
  • 现代CSS实战:用变量与嵌套重构可维护的前端样式
  • 【GPIO】从STM32F103入门GPIO寄存器
  • 腿姐政治笔记唯物辩证法(2)(12356)
  • 面试遇到的问题
  • 使用JS编写用户信息采集表单
  • 利用android studio,对图片资源进行二次压缩
  • 网络编程-epoll模型/udp通信
  • Node.js 中http 和 http/2 是两个不同模块对比
  • AutoGPT vs BabyAGI:自主任务执行框架对比与选型深度分析
  • python的形成性考核管理系统
  • 1.easypan-登录注册
  • P3842 [TJOI2007] 线段
  • 基于多智能体强化学习的医疗检索增强生成系统研究—MMOA-RAG架构设计与实现
  • 编程技能:多文件编译
  • c++图形题练习程序
  • LVS三种模式实战
  • 图机器学习(6)——图自编码器
  • 【电脑】显卡(GPU)的基础知识
  • 【轨物方案】当补贴退潮,光伏电站如何回归价值本质?
  • MySQL数据库----函数
  • 【PTA数据结构 | C语言版】二叉树前序序列化
  • 跨平台游戏引擎 Axmol-2.7.1 发布
  • git起步
  • 微信小程序翻书效果